diff options
161 files changed, 10175 insertions, 6673 deletions
diff --git a/api/current.xml b/api/current.xml index 9708388..0a96169 100644 --- a/api/current.xml +++ b/api/current.xml @@ -848,6 +848,17 @@ visibility="public" > </field> +<field name="SDCARD_WRITE" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.permission.SDCARD_WRITE"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="SEND_SMS" type="java.lang.String" transient="false" @@ -1283,6 +1294,17 @@ visibility="public" > </field> +<field name="STORAGE" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.permission-group.STORAGE"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="SYSTEM_TOOLS" type="java.lang.String" transient="false" @@ -73253,19 +73275,6 @@ visibility="public" > </constructor> -<method name="_glGetString" - return="java.lang.String" - abstract="false" - native="true" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="name" type="int"> -</parameter> -</method> <method name="glActiveTexture" return="void" abstract="false" @@ -74070,9 +74079,9 @@ <method name="glGetString" return="java.lang.String" abstract="false" - native="false" + native="true" synchronized="false" - static="false" + static="true" final="false" deprecated="not deprecated" visibility="public" diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 1bed706..cb660c7 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -440,9 +440,13 @@ public final class PendingIntent implements Parcelable { @Override public String toString() { - return "PendingIntent{" - + Integer.toHexString(System.identityHashCode(this)) - + " target " + (mTarget != null ? mTarget.asBinder() : null) + "}"; + StringBuilder sb = new StringBuilder(128); + sb.append("PendingIntent{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(": "); + sb.append(mTarget != null ? mTarget.asBinder() : null); + sb.append('}'); + return sb.toString(); } public int describeContents() { diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index a0cdb63..3d89ad7 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -16,24 +16,24 @@ package android.app; +import static android.app.SuggestionsAdapter.getColumnString; + import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.server.search.SearchableInfo; import android.speech.RecognizerIntent; @@ -45,7 +45,10 @@ import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; +import android.view.Menu; +import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; @@ -53,17 +56,14 @@ import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AutoCompleteTextView; import android.widget.Button; -import android.widget.CursorAdapter; import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.ListView; -import android.widget.SimpleCursorAdapter; import android.widget.TextView; -import android.widget.WrapperListAdapter; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; -import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicLong; /** @@ -75,59 +75,66 @@ import java.util.concurrent.atomic.AtomicLong; public class SearchDialog extends Dialog implements OnItemClickListener, OnItemSelectedListener { // Debugging support - final static String LOG_TAG = "SearchDialog"; - private static final int DBG_LOG_TIMING = 0; - final static int DBG_JAM_THREADING = 0; + private static final boolean DBG = false; + private static final String LOG_TAG = "SearchDialog"; + private static final boolean DBG_LOG_TIMING = false; - // interaction with runtime - IntentFilter mCloseDialogsFilter; - IntentFilter mPackageFilter; - private static final String INSTANCE_KEY_COMPONENT = "comp"; private static final String INSTANCE_KEY_APPDATA = "data"; private static final String INSTANCE_KEY_GLOBALSEARCH = "glob"; private static final String INSTANCE_KEY_DISPLAY_QUERY = "dQry"; private static final String INSTANCE_KEY_DISPLAY_SEL_START = "sel1"; private static final String INSTANCE_KEY_DISPLAY_SEL_END = "sel2"; - private static final String INSTANCE_KEY_USER_QUERY = "uQry"; - private static final String INSTANCE_KEY_SUGGESTION_QUERY = "sQry"; private static final String INSTANCE_KEY_SELECTED_ELEMENT = "slEl"; private static final int INSTANCE_SELECTED_BUTTON = -2; private static final int INSTANCE_SELECTED_QUERY = -1; - + + // interaction with runtime + private IntentFilter mCloseDialogsFilter; + private IntentFilter mPackageFilter; + // views & widgets private TextView mBadgeLabel; - private AutoCompleteTextView mSearchTextField; + private SearchAutoComplete mSearchAutoComplete; private Button mGoButton; private ImageButton mVoiceButton; + private View mSearchPlate; // interaction with searchable application + private SearchableInfo mSearchable; private ComponentName mLaunchComponent; private Bundle mAppSearchData; private boolean mGlobalSearchMode; private Context mActivityContext; - - // interaction with the search manager service - private SearchableInfo mSearchable; - - // support for suggestions - private String mUserQuery = null; - private int mUserQuerySelStart; - private int mUserQuerySelEnd; - private boolean mLeaveJammedQueryOnRefocus = false; - private String mPreviousSuggestionQuery = null; - private int mPresetSelection = -1; - private String mSuggestionAction = null; - private Uri mSuggestionData = null; - private String mSuggestionQuery = null; + // stack of previous searchables, to support the BACK key after + // SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE. + // The top of the stack (= previous searchable) is the last element of the list, + // since adding and removing is efficient at the end of an ArrayList. + private ArrayList<ComponentName> mPreviousComponents; + // For voice searching private Intent mVoiceWebSearchIntent; private Intent mVoiceAppSearchIntent; // support for AutoCompleteTextView suggestions display private SuggestionsAdapter mSuggestionsAdapter; - + + // Whether to rewrite queries when selecting suggestions + // TODO: This is disabled because of problems with persistent selections + // causing non-user-initiated rewrites. + private static final boolean REWRITE_QUERIES = false; + + // The query entered by the user. This is not changed when selecting a suggestion + // that modifies the contents of the text field. But if the user then edits + // the suggestion, the resulting string is saved. + private String mUserQuery; + + // A weak map of drawables we've gotten from other packages, so we don't load them + // more than once. + private final WeakHashMap<String, Drawable> mOutsideDrawablesCache = + new WeakHashMap<String, Drawable>(); + /** * Constructor - fires it up and makes it look like the search UI. * @@ -153,25 +160,29 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS theWindow.setLayout(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); WindowManager.LayoutParams lp = theWindow.getAttributes(); - lp.setTitle("Search Dialog"); lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE; theWindow.setAttributes(lp); // get the view elements for local access mBadgeLabel = (TextView) findViewById(com.android.internal.R.id.search_badge); - mSearchTextField = (AutoCompleteTextView) + mSearchAutoComplete = (SearchAutoComplete) findViewById(com.android.internal.R.id.search_src_text); mGoButton = (Button) findViewById(com.android.internal.R.id.search_go_btn); mVoiceButton = (ImageButton) findViewById(com.android.internal.R.id.search_voice_btn); + mSearchPlate = findViewById(com.android.internal.R.id.search_plate); // attach listeners - mSearchTextField.addTextChangedListener(mTextWatcher); - mSearchTextField.setOnKeyListener(mTextKeyListener); + mSearchAutoComplete.addTextChangedListener(mTextWatcher); + mSearchAutoComplete.setOnKeyListener(mTextKeyListener); + mSearchAutoComplete.setOnItemClickListener(this); + mSearchAutoComplete.setOnItemSelectedListener(this); mGoButton.setOnClickListener(mGoButtonClickListener); mGoButton.setOnKeyListener(mButtonsKeyListener); mVoiceButton.setOnClickListener(mVoiceButtonClickListener); mVoiceButton.setOnKeyListener(mButtonsKeyListener); + mSearchAutoComplete.setSearchDialog(this); + // pre-hide all the extraneous elements mBadgeLabel.setVisibility(View.GONE); @@ -199,7 +210,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS /** * Set up the search dialog * - * @param Returns true if search dialog launched, false if not + * @return true if search dialog launched, false if not */ public boolean show(String initialQuery, boolean selectInitialQuery, ComponentName componentName, Bundle appSearchData, boolean globalSearch) { @@ -208,75 +219,65 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // in this case, just discard the "show" request return true; } - - // Get searchable info from search manager and use to set up other elements of UI - // Do this first so we can get out quickly if there's nothing to search - ISearchManager sms; - sms = ISearchManager.Stub.asInterface(ServiceManager.getService(Context.SEARCH_SERVICE)); - try { - mSearchable = sms.getSearchableInfo(componentName, globalSearch); - } catch (RemoteException e) { - mSearchable = null; + + // set up the searchable and show the dialog + if (!show(componentName, appSearchData, globalSearch)) { + return false; + } + + // finally, load the user's initial text (which may trigger suggestions) + setUserQuery(initialQuery); + if (selectInitialQuery) { + mSearchAutoComplete.selectAll(); + } + + return true; + } + + /** + * Sets up the search dialog and shows it. + * + * @return <code>true</code> if search dialog launched + */ + private boolean show(ComponentName componentName, Bundle appSearchData, + boolean globalSearch) { + + if (DBG) { + Log.d(LOG_TAG, "show(" + componentName + ", " + + appSearchData + ", " + globalSearch + ")"); } + + mSearchable = SearchManager.getSearchableInfo(componentName, globalSearch); if (mSearchable == null) { // unfortunately, we can't log here. it would be logspam every time the user // clicks the "search" key on a non-search app return false; } - // OK, we're going to show ourselves - super.show(); - - setupSearchableInfo(); - mLaunchComponent = componentName; mAppSearchData = appSearchData; - mGlobalSearchMode = globalSearch; - - // receive broadcasts - getContext().registerReceiver(mBroadcastReceiver, mCloseDialogsFilter); - getContext().registerReceiver(mBroadcastReceiver, mPackageFilter); + // Using globalSearch here is just an optimization, just calling + // isDefaultSearchable() should always give the same result. + mGlobalSearchMode = globalSearch || SearchManager.isDefaultSearchable(mSearchable); + mActivityContext = mSearchable.getActivityContext(getContext()); - // configure the autocomplete aspects of the input box - mSearchTextField.setOnItemClickListener(this); - mSearchTextField.setOnItemSelectedListener(this); - - // This conversion is necessary to force a preload of the EditText and thus force - // suggestions to be presented (even for an empty query) - if (initialQuery == null) { - initialQuery = ""; // This forces the preload to happen, triggering suggestions + // show the dialog. this will call onStart(). + if (!isShowing()) { + show(); } - // attach the suggestions adapter, if suggestions are available - // The existence of a suggestions authority is the proxy for "suggestions available here" - if (mSearchable.getSuggestAuthority() == null) { - mSuggestionsAdapter = null; - mSearchTextField.setAdapter(mSuggestionsAdapter); - mSearchTextField.setText(initialQuery); - } else { - mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable, - mSearchTextField); - mSearchTextField.setAdapter(mSuggestionsAdapter); - - // finally, load the user's initial text (which may trigger suggestions) - mSuggestionsAdapter.setNonUserQuery(false); - mSearchTextField.setText(initialQuery); - } + updateUI(); - if (selectInitialQuery) { - mSearchTextField.selectAll(); - } else { - mSearchTextField.setSelection(initialQuery.length()); - } return true; } - - /** - * The default show() for this Dialog is not supported. - */ + @Override - public void show() { - return; + protected void onStart() { + super.onStart(); + + // receive broadcasts + getContext().registerReceiver(mBroadcastReceiver, mCloseDialogsFilter); + getContext().registerReceiver(mBroadcastReceiver, mPackageFilter); } /** @@ -289,6 +290,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS public void onStop() { super.onStop(); + // TODO: Removing the listeners means that they never get called, since + // Dialog.dismissDialog() calls onStop() before sendDismissMessage(). setOnCancelListener(null); setOnDismissListener(null); @@ -299,26 +302,36 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // This is OK - it just means we didn't have any registered } - // close any leftover cursor - if (mSuggestionsAdapter != null) { - mSuggestionsAdapter.changeCursor(null); - } + closeSuggestionsAdapter(); // dump extra memory we're hanging on to mLaunchComponent = null; mAppSearchData = null; mSearchable = null; - mSuggestionAction = null; - mSuggestionData = null; - mSuggestionQuery = null; mActivityContext = null; - mPreviousSuggestionQuery = null; mUserQuery = null; + mPreviousComponents = null; + } + + /** + * Closes and gets rid of the suggestions adapter. + */ + private void closeSuggestionsAdapter() { + // remove the adapter from the autocomplete first, to avoid any updates + // when we drop the cursor + mSearchAutoComplete.setAdapter((SuggestionsAdapter)null); + // close any leftover cursor + if (mSuggestionsAdapter != null) { + mSuggestionsAdapter.changeCursor(null); + } + mSuggestionsAdapter = null; } /** * Save the minimal set of data necessary to recreate the search * + * TODO: go through this and make sure that it saves everything that is needed + * * @return A bundle with the state of the dialog. */ @Override @@ -331,16 +344,14 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS bundle.putBoolean(INSTANCE_KEY_GLOBALSEARCH, mGlobalSearchMode); // UI state - bundle.putString(INSTANCE_KEY_DISPLAY_QUERY, mSearchTextField.getText().toString()); - bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_START, mSearchTextField.getSelectionStart()); - bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_END, mSearchTextField.getSelectionEnd()); - bundle.putString(INSTANCE_KEY_USER_QUERY, mUserQuery); - bundle.putString(INSTANCE_KEY_SUGGESTION_QUERY, mPreviousSuggestionQuery); + bundle.putString(INSTANCE_KEY_DISPLAY_QUERY, mSearchAutoComplete.getText().toString()); + bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_START, mSearchAutoComplete.getSelectionStart()); + bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_END, mSearchAutoComplete.getSelectionEnd()); int selectedElement = INSTANCE_SELECTED_QUERY; if (mGoButton.isFocused()) { selectedElement = INSTANCE_SELECTED_BUTTON; - } else if (mSearchTextField.isPopupShowing()) { + } else if (mSearchAutoComplete.isPopupShowing()) { selectedElement = 0; // TODO mSearchTextField.getListSelection() // 0..n } bundle.putInt(INSTANCE_KEY_SELECTED_ELEMENT, selectedElement); @@ -350,6 +361,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS /** * Restore the state of the dialog from a previously saved bundle. + * + * TODO: go through this and make sure that it saves everything that is saved * * @param savedInstanceState The state of the dialog previously saved by * {@link #onSaveInstanceState()}. @@ -365,26 +378,17 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS String displayQuery = savedInstanceState.getString(INSTANCE_KEY_DISPLAY_QUERY); int querySelStart = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_START, -1); int querySelEnd = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_END, -1); - String userQuery = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY); int selectedElement = savedInstanceState.getInt(INSTANCE_KEY_SELECTED_ELEMENT); - String suggestionQuery = savedInstanceState.getString(INSTANCE_KEY_SUGGESTION_QUERY); // show the dialog. skip any show/hide animation, we want to go fast. // send the text that actually generates the suggestions here; we'll replace the display // text as necessary in a moment. - if (!show(suggestionQuery, false, launchComponent, appSearchData, globalSearch)) { + if (!show(displayQuery, false, launchComponent, appSearchData, globalSearch)) { // for some reason, we couldn't re-instantiate return; } - if (mSuggestionsAdapter != null) { - mSuggestionsAdapter.setNonUserQuery(true); - } - mSearchTextField.setText(displayQuery); - // TODO because the new query is (not) processed in another thread, we can't just - // take away this flag (yet). The better solution here is going to require a new API - // in AutoCompleteTextView which allows us to change the text w/o changing the suggestions. -// mSuggestionsAdapter.setNonUserQuery(false); + mSearchAutoComplete.setText(displayQuery); // clean up the selection state switch (selectedElement) { @@ -395,21 +399,19 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS break; case INSTANCE_SELECTED_QUERY: if (querySelStart >= 0 && querySelEnd >= 0) { - mSearchTextField.requestFocus(); - mSearchTextField.setSelection(querySelStart, querySelEnd); + mSearchAutoComplete.requestFocus(); + mSearchAutoComplete.setSelection(querySelStart, querySelEnd); } break; default: - // defer selecting a list element until suggestion list appears - mPresetSelection = selectedElement; - // TODO mSearchTextField.setListSelection(selectedElement) + // TODO: defer selecting a list element until suggestion list appears +// mSearchAutoComplete.setListSelection(selectedElement) break; } } /** - * Hook for updating layout on a rotation - * + * Called after resources have changed, e.g. after screen rotation or locale change. */ public void onConfigurationChanged(Configuration newConfig) { if (isShowing()) { @@ -419,15 +421,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS updateQueryHint(); } } - + /** - * Use SearchableInfo record (from search manager service) to preconfigure the UI in various - * ways. + * Update the UI according to the info in the current value of {@link #mSearchable}. */ - private void setupSearchableInfo() { + private void updateUI() { if (mSearchable != null) { - mActivityContext = mSearchable.getActivityContext(getContext()); - + updateSearchAutoComplete(); updateSearchButton(); updateSearchBadge(); updateQueryHint(); @@ -449,24 +449,38 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS inputType |= InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; } } - mSearchTextField.setInputType(inputType); - mSearchTextField.setImeOptions(mSearchable.getImeOptions()); + mSearchAutoComplete.setInputType(inputType); + mSearchAutoComplete.setImeOptions(mSearchable.getImeOptions()); } } - + /** - * The list of installed packages has just changed. This means that our current context - * may no longer be valid. This would only happen if a package is installed/removed exactly - * when the search bar is open. So for now we're just going to close the search - * bar. - * - * Anything fancier would require some checks to see if the user's context was still valid. - * Which would be messier. + * Updates the auto-complete text view. */ - public void onPackageListChange() { - cancel(); + private void updateSearchAutoComplete() { + // close any existing suggestions adapter + closeSuggestionsAdapter(); + + mSearchAutoComplete.setDropDownAnimationStyle(0); // no animation + mSearchAutoComplete.setThreshold(0); // always allow zero-query suggestions + + if (mGlobalSearchMode) { + mSearchAutoComplete.setDropDownAlwaysVisible(true); // fill space until results come in + mSearchAutoComplete.setDropDownDismissedOnCompletion(false); + } else { + mSearchAutoComplete.setDropDownAlwaysVisible(false); + mSearchAutoComplete.setDropDownDismissedOnCompletion(true); + } + + // attach the suggestions adapter, if suggestions are available + // The existence of a suggestions authority is the proxy for "suggestions available here" + if (mSearchable.getSuggestAuthority() != null) { + mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable, + mOutsideDrawablesCache); + mSearchAutoComplete.setAdapter(mSuggestionsAdapter); + } } - + /** * Update the text in the search button. Note: This is deprecated functionality, for * 1.0 compatibility only. @@ -481,26 +495,40 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS iconLabel = getContext().getResources(). getDrawable(com.android.internal.R.drawable.ic_btn_search); } - mGoButton.setText(textLabel); + mGoButton.setText(textLabel); mGoButton.setCompoundDrawablesWithIntrinsicBounds(iconLabel, null, null, null); } /** - * Setup the search "Badge" if request by mode flags. + * Setup the search "Badge" if requested by mode flags. */ private void updateSearchBadge() { // assume both hidden int visibility = View.GONE; Drawable icon = null; - String text = null; + CharSequence text = null; // optionally show one or the other. if (mSearchable.mBadgeIcon) { icon = mActivityContext.getResources().getDrawable(mSearchable.getIconId()); visibility = View.VISIBLE; + if (DBG) Log.d(LOG_TAG, "Using badge icon: " + mSearchable.getIconId()); } else if (mSearchable.mBadgeLabel) { text = mActivityContext.getResources().getText(mSearchable.getLabelId()).toString(); visibility = View.VISIBLE; + if (DBG) Log.d(LOG_TAG, "Using badge label: " + mSearchable.getLabelId()); + } else if (!mGlobalSearchMode) { + // Get the localized name of the application which we are doing search in. + try { + PackageManager pm = getContext().getPackageManager(); + ActivityInfo info = pm.getActivityInfo(mLaunchComponent, 0); + text = pm.getApplicationLabel(info.applicationInfo); + visibility = View.VISIBLE; + if (DBG) Log.d(LOG_TAG, "Using application label: " + text); + } catch (NameNotFoundException e) { + // app not found, fine, don't use its name for the label + Log.w(LOG_TAG, mLaunchComponent + " not found."); + } } mBadgeLabel.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null); @@ -520,7 +548,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS hint = mActivityContext.getString(hintId); } } - mSearchTextField.setHint(hint); + mSearchAutoComplete.setHint(hint); } } @@ -548,63 +576,129 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mVoiceButton.setVisibility(visibility); } + /* + * Menu. + */ + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Show search settings menu item if anyone handles the intent for it + Intent settingsIntent = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS); + PackageManager pm = getContext().getPackageManager(); + ActivityInfo activityInfo = settingsIntent.resolveActivityInfo(pm, 0); + if (activityInfo != null) { + settingsIntent.setClassName(activityInfo.applicationInfo.packageName, + activityInfo.name); + String label = getActivityLabel(activityInfo); + menu.add(Menu.NONE, Menu.NONE, Menu.NONE, label) + .setIcon(android.R.drawable.ic_menu_preferences) + .setAlphabeticShortcut('P') + .setIntent(settingsIntent); + return true; + } + return super.onCreateOptionsMenu(menu); + } + + // TODO: shouldn't this be in PackageManager? + private String getActivityLabel(ActivityInfo activityInfo) { + PackageManager pm = getContext().getPackageManager(); + try { + int labelRes = activityInfo.labelRes; + if (labelRes == 0) { + return null; + } + Resources r = pm.getResourcesForApplication(activityInfo.applicationInfo); + return r.getString(labelRes); + } catch (NameNotFoundException ex) { + return null; + } + } + /** * Listeners of various types */ /** + * {@link Dialog#onTouchEvent(MotionEvent)} will cancel the dialog only when the + * touch is outside the window. But the window includes space for the drop-down, + * so we also cancel on taps outside the search bar when the drop-down is not showing. + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + // cancel if the drop-down is not showing and the touch event was outside the search plate + if (!mSearchAutoComplete.isPopupShowing() && isOutOfBounds(mSearchPlate, event)) { + if (DBG) Log.d(LOG_TAG, "Pop-up not showing and outside of search plate."); + cancel(); + return true; + } + // Let Dialog handle events outside the window while the pop-up is showing. + return super.onTouchEvent(event); + } + + private boolean isOutOfBounds(View v, MotionEvent event) { + final int x = (int) event.getX(); + final int y = (int) event.getY(); + final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); + return (x < -slop) || (y < -slop) + || (x > (v.getWidth()+slop)) + || (y > (v.getHeight()+slop)); + } + + /** * Dialog's OnKeyListener implements various search-specific functionality * * @param keyCode This is the keycode of the typed key, and is the same value as - * found in the KeyEvent parameter. + * found in the KeyEvent parameter. * @param event The complete event record for the typed key * * @return Return true if the event was handled here, or false if not. */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_BACK: - cancel(); + if (DBG) Log.d(LOG_TAG, "onKeyDown(" + keyCode + "," + event + ")"); + + // handle back key to go back to previous searchable, etc. + if (handleBackKey(keyCode, event)) { return true; - case KeyEvent.KEYCODE_SEARCH: - if (TextUtils.getTrimmedLength(mSearchTextField.getText()) != 0) { - launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null); + } + + // search or cancel on search key + if (keyCode == KeyEvent.KEYCODE_SEARCH) { + if (!mSearchAutoComplete.isEmpty()) { + launchQuerySearch(); } else { cancel(); } return true; - default: - SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); - if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) { - launchQuerySearch(keyCode, actionKey.mQueryActionMsg); - return true; - } - break; } + + // if it's an action specified by the searchable activity, launch the + // entered query with the action key + SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); + if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) { + launchQuerySearch(keyCode, actionKey.mQueryActionMsg); + return true; + } + return false; } - + /** * Callback to watch the textedit field for empty/non-empty */ private TextWatcher mTextWatcher = new TextWatcher() { - public void beforeTextChanged(CharSequence s, int start, int - before, int after) { } + public void beforeTextChanged(CharSequence s, int start, int before, int after) { } public void onTextChanged(CharSequence s, int start, int before, int after) { - if (DBG_LOG_TIMING == 1) { + if (DBG_LOG_TIMING) { dbgLogTiming("onTextChanged()"); } updateWidgetState(); - // Only do suggestions if actually typed by user - if ((mSuggestionsAdapter != null) && !mSuggestionsAdapter.getNonUserQuery()) { - mPreviousSuggestionQuery = s.toString(); - mUserQuery = mSearchTextField.getText().toString(); - mUserQuerySelStart = mSearchTextField.getSelectionStart(); - mUserQuerySelEnd = mSearchTextField.getSelectionEnd(); + if (!mSearchAutoComplete.isPerformingCompletion()) { + // The user changed the query, remember it. + mUserQuery = s == null ? "" : s.toString(); } } @@ -616,64 +710,34 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ private void updateWidgetState() { // enable the button if we have one or more non-space characters - boolean enabled = - TextUtils.getTrimmedLength(mSearchTextField.getText()) != 0; - + boolean enabled = !mSearchAutoComplete.isEmpty(); mGoButton.setEnabled(enabled); mGoButton.setFocusable(enabled); } - private final static String[] ONE_LINE_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1 }; - private final static String[] ONE_LINE_ICONS_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1, - SearchManager.SUGGEST_COLUMN_ICON_1, - SearchManager.SUGGEST_COLUMN_ICON_2}; - private final static String[] TWO_LINE_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1, - SearchManager.SUGGEST_COLUMN_TEXT_2 }; - private final static String[] TWO_LINE_ICONS_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1, - SearchManager.SUGGEST_COLUMN_TEXT_2, - SearchManager.SUGGEST_COLUMN_ICON_1, - SearchManager.SUGGEST_COLUMN_ICON_2 }; - - private final static int[] ONE_LINE_TO = {com.android.internal.R.id.text1}; - private final static int[] ONE_LINE_ICONS_TO = {com.android.internal.R.id.text1, - com.android.internal.R.id.icon1, - com.android.internal.R.id.icon2}; - private final static int[] TWO_LINE_TO = {com.android.internal.R.id.text1, - com.android.internal.R.id.text2}; - private final static int[] TWO_LINE_ICONS_TO = {com.android.internal.R.id.text1, - com.android.internal.R.id.text2, - com.android.internal.R.id.icon1, - com.android.internal.R.id.icon2}; - - /** - * Safely retrieve the suggestions cursor adapter from the ListView - * - * @param adapterView The ListView containing our adapter - * @result The CursorAdapter that we installed, or null if not set - */ - private static CursorAdapter getSuggestionsAdapter(AdapterView<?> adapterView) { - CursorAdapter result = null; - if (adapterView != null) { - Object ad = adapterView.getAdapter(); - if (ad instanceof CursorAdapter) { - result = (CursorAdapter) ad; - } else if (ad instanceof WrapperListAdapter) { - result = (CursorAdapter) ((WrapperListAdapter)ad).getWrappedAdapter(); - } - } - return result; - } - /** * React to typing in the GO search button by refocusing to EditText. * Continue typing the query. */ View.OnKeyListener mButtonsKeyListener = new View.OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { - // also guard against possible race conditions (late arrival after dismiss) - if (mSearchable != null) { - return refocusingKeyListener(v, keyCode, event); + // guard against possible race conditions + if (mSearchable == null) { + return false; + } + + if (!event.isSystem() && + (keyCode != KeyEvent.KEYCODE_DPAD_UP) && + (keyCode != KeyEvent.KEYCODE_DPAD_DOWN) && + (keyCode != KeyEvent.KEYCODE_DPAD_LEFT) && + (keyCode != KeyEvent.KEYCODE_DPAD_RIGHT) && + (keyCode != KeyEvent.KEYCODE_DPAD_CENTER)) { + // restore focus and give key to EditText ... + if (mSearchAutoComplete.requestFocus()) { + return mSearchAutoComplete.dispatchKeyEvent(event); + } } + return false; } }; @@ -683,10 +747,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ View.OnClickListener mGoButtonClickListener = new View.OnClickListener() { public void onClick(View v) { - // also guard against possible race conditions (late arrival after dismiss) - if (mSearchable != null) { - launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null); + // guard against possible race conditions + if (mSearchable == null) { + return; } + launchQuerySearch(); } }; @@ -695,14 +760,16 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ View.OnClickListener mVoiceButtonClickListener = new View.OnClickListener() { public void onClick(View v) { + // guard against possible race conditions + if (mSearchable == null) { + return; + } try { if (mSearchable.getVoiceSearchLaunchWebSearch()) { getContext().startActivity(mVoiceWebSearchIntent); - dismiss(); } else if (mSearchable.getVoiceSearchLaunchRecognizer()) { Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent); getContext().startActivity(appSearchIntent); - dismiss(); } } catch (ActivityNotFoundException e) { // Should not happen, since we check the availability of @@ -778,136 +845,56 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ View.OnKeyListener mTextKeyListener = new View.OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - cancel(); - return true; - } - // also guard against possible race conditions (late arrival after dismiss) - if (mSearchable != null && - TextUtils.getTrimmedLength(mSearchTextField.getText()) > 0) { - if (DBG_LOG_TIMING == 1) { - dbgLogTiming("doTextKey()"); - } - // dispatch "typing in the list" first - if (mSearchTextField.isPopupShowing() && - mSearchTextField.getListSelection() != ListView.INVALID_POSITION) { - return onSuggestionsKey(v, keyCode, event); - } - // otherwise, dispatch an "edit view" key - switch (keyCode) { - case KeyEvent.KEYCODE_ENTER: - if (event.getAction() == KeyEvent.ACTION_UP) { - v.cancelLongPress(); - launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null); - return true; - } - break; - case KeyEvent.KEYCODE_DPAD_DOWN: - // capture the EditText state, so we can restore the user entry later - mUserQuery = mSearchTextField.getText().toString(); - mUserQuerySelStart = mSearchTextField.getSelectionStart(); - mUserQuerySelEnd = mSearchTextField.getSelectionEnd(); - // pass through - we're just watching here - break; - default: - if (event.getAction() == KeyEvent.ACTION_DOWN) { - SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); - if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) { - launchQuerySearch(keyCode, actionKey.mQueryActionMsg); - return true; - } - } - break; - } + // guard against possible race conditions + if (mSearchable == null) { + return false; } - return false; - } - }; - - /** - * React to the user typing while the suggestions are focused. First, check for action - * keys. If not handled, try refocusing regular characters into the EditText. In this case, - * replace the query text (start typing fresh text). - */ - private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) { - boolean handled = false; - // also guard against possible race conditions (late arrival after dismiss) - if (mSearchable != null) { - handled = doSuggestionsKey(v, keyCode, event); - } - return handled; - } - - /** - * Per UI design, we're going to "steer" any typed keystrokes back into the EditText - * box, even if the user has navigated the focus to the dropdown or to the GO button. - * - * @param v The view into which the keystroke was typed - * @param keyCode keyCode of entered key - * @param event Full KeyEvent record of entered key - */ - private boolean refocusingKeyListener(View v, int keyCode, KeyEvent event) { - boolean handled = false; - if (!event.isSystem() && - (keyCode != KeyEvent.KEYCODE_DPAD_UP) && - (keyCode != KeyEvent.KEYCODE_DPAD_DOWN) && - (keyCode != KeyEvent.KEYCODE_DPAD_LEFT) && - (keyCode != KeyEvent.KEYCODE_DPAD_RIGHT) && - (keyCode != KeyEvent.KEYCODE_DPAD_CENTER)) { - // restore focus and give key to EditText ... - // but don't replace the user's query - mLeaveJammedQueryOnRefocus = true; - if (mSearchTextField.requestFocus()) { - handled = mSearchTextField.dispatchKeyEvent(event); + if (DBG_LOG_TIMING) dbgLogTiming("doTextKey()"); + if (DBG) { + Log.d(LOG_TAG, "mTextListener.onKey(" + keyCode + "," + event + + "), selection: " + mSearchAutoComplete.getListSelection()); } - mLeaveJammedQueryOnRefocus = false; - } - return handled; - } - - /** - * Update query text based on transitions in and out of suggestions list. - */ - /* - * TODO - figure out if this logic is required for the autocomplete text view version - - OnFocusChangeListener mSuggestFocusListener = new OnFocusChangeListener() { - public void onFocusChange(View v, boolean hasFocus) { - // also guard against possible race conditions (late arrival after dismiss) - if (mSearchable == null) { - return; + + // If a suggestion is selected, handle enter, search key, and action keys + // as presses on the selected suggestion + if (mSearchAutoComplete.isPopupShowing() && + mSearchAutoComplete.getListSelection() != ListView.INVALID_POSITION) { + return onSuggestionsKey(v, keyCode, event); } - // Update query text based on navigation in to/out of the suggestions list - if (hasFocus) { - // Entering the list view - record selection point from user's query - mUserQuery = mSearchTextField.getText().toString(); - mUserQuerySelStart = mSearchTextField.getSelectionStart(); - mUserQuerySelEnd = mSearchTextField.getSelectionEnd(); - // then update the query to match the entered selection - jamSuggestionQuery(true, mSuggestionsList, - mSuggestionsList.getSelectedItemPosition()); - } else { - // Exiting the list view - - if (mSuggestionsList.getSelectedItemPosition() < 0) { - // Direct exit - Leave new suggestion in place (do nothing) - } else { - // Navigation exit - restore user's query text - if (!mLeaveJammedQueryOnRefocus) { - jamSuggestionQuery(false, null, -1); + + // If there is text in the query box, handle enter, and action keys + // The search key is handled by the dialog's onKeyDown(). + if (!mSearchAutoComplete.isEmpty()) { + if (keyCode == KeyEvent.KEYCODE_ENTER + && event.getAction() == KeyEvent.ACTION_UP) { + v.cancelLongPress(); + launchQuerySearch(); + return true; + } + if (event.getAction() == KeyEvent.ACTION_DOWN) { + SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); + if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) { + launchQuerySearch(keyCode, actionKey.mQueryActionMsg); + return true; } } } - + return false; } }; - */ - + /** - * This is the listener for the ACTION_CLOSE_SYSTEM_DIALOGS intent. It's an indication that - * we should close ourselves immediately, in order to allow a higher-priority UI to take over + * When the ACTION_CLOSE_SYSTEM_DIALOGS intent is received, we should close ourselves + * immediately, in order to allow a higher-priority UI to take over * (e.g. phone call received). + * + * When a package is added, removed or changed, our current context + * may no longer be valid. This would only happen if a package is installed/removed exactly + * when the search bar is open. So for now we're just going to close the search + * bar. + * Anything fancier would require some checks to see if the user's context was still valid. + * Which would be messier. */ private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -918,7 +905,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } else if (Intent.ACTION_PACKAGE_ADDED.equals(action) || Intent.ACTION_PACKAGE_REMOVED.equals(action) || Intent.ACTION_PACKAGE_CHANGED.equals(action)) { - onPackageListChange(); + cancel(); } } }; @@ -938,58 +925,45 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } /** - * Various ways to launch searches + * React to the user typing while in the suggestions list. First, check for action + * keys. If not handled, try refocusing regular characters into the EditText. */ - - /** - * React to the user clicking the "GO" button. Hide the UI and launch a search. - * - * @param actionKey Pass a keycode if the launch was triggered by an action key. Pass - * KeyEvent.KEYCODE_UNKNOWN for no actionKey code. - * @param actionMsg Pass the suggestion-provided message if the launch was triggered by an - * action key. Pass null for no actionKey message. - */ - private void launchQuerySearch(int actionKey, final String actionMsg) { - final String query = mSearchTextField.getText().toString(); - final Bundle appData = mAppSearchData; - final SearchableInfo si = mSearchable; // cache briefly (dismiss() nulls it) - dismiss(); - sendLaunchIntent(Intent.ACTION_SEARCH, null, query, appData, actionKey, actionMsg, si); - } - - /** - * React to the user typing an action key while in the suggestions list - */ - private boolean doSuggestionsKey(View v, int keyCode, KeyEvent event) { - // Exit early in case of race condition + private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) { + // guard against possible race conditions (late arrival after dismiss) + if (mSearchable == null) { + return false; + } if (mSuggestionsAdapter == null) { return false; } if (event.getAction() == KeyEvent.ACTION_DOWN) { - if (DBG_LOG_TIMING == 1) { - dbgLogTiming("doSuggestionsKey()"); + if (DBG_LOG_TIMING) { + dbgLogTiming("onSuggestionsKey()"); } // First, check for enter or search (both of which we'll treat as a "click") if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH) { - int position = mSearchTextField.getListSelection(); - return launchSuggestion(mSuggestionsAdapter, position); + int position = mSearchAutoComplete.getListSelection(); + return launchSuggestion(position); } // Next, check for left/right moves, which we use to "return" the user to the edit view if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { - // give "focus" to text editor, but don't restore the user's original query + // give "focus" to text editor, with cursor at the beginning if + // left key, at end if right key + // TODO: Reverse left/right for right-to-left languages, e.g. Arabic int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? - 0 : mSearchTextField.length(); - mSearchTextField.setSelection(selPoint); - mSearchTextField.setListSelection(0); - mSearchTextField.clearListSelection(); + 0 : mSearchAutoComplete.length(); + mSearchAutoComplete.setSelection(selPoint); + mSearchAutoComplete.setListSelection(0); + mSearchAutoComplete.clearListSelection(); return true; } // Next, check for an "up and out" move - if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mSearchTextField.getListSelection()) { - jamSuggestionQuery(false, null, -1); + if (keyCode == KeyEvent.KEYCODE_DPAD_UP + && 0 == mSearchAutoComplete.getListSelection()) { + restoreUserQuery(); // let ACTV complete the move return false; } @@ -999,158 +973,194 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if ((actionKey != null) && ((actionKey.mSuggestActionMsg != null) || (actionKey.mSuggestActionMsgColumn != null))) { - // launch suggestion using action key column - int position = mSearchTextField.getListSelection(); - if (position >= 0) { + // launch suggestion using action key column + int position = mSearchAutoComplete.getListSelection(); + if (position != ListView.INVALID_POSITION) { Cursor c = mSuggestionsAdapter.getCursor(); if (c.moveToPosition(position)) { final String actionMsg = getActionKeyMessage(c, actionKey); if (actionMsg != null && (actionMsg.length() > 0)) { - // shut down search bar and launch the activity - // cache everything we need because dismiss releases mems - setupSuggestionIntent(c, mSearchable); - final String query = mSearchTextField.getText().toString(); - final Bundle appData = mAppSearchData; - SearchableInfo si = mSearchable; - String suggestionAction = mSuggestionAction; - Uri suggestionData = mSuggestionData; - String suggestionQuery = mSuggestionQuery; - dismiss(); - sendLaunchIntent(suggestionAction, suggestionData, - suggestionQuery, appData, - keyCode, actionMsg, si); - return true; + return launchSuggestion(position, keyCode, actionMsg); } } } } } return false; - } + } + + /** + * Launch a search for the text in the query text field. + */ + protected void launchQuerySearch() { + launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null); + } /** - * Set or reset the user query to follow the selections in the suggestions + * Launch a search for the text in the query text field. + * + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or <code>null</code> if none. + */ + protected void launchQuerySearch(int actionKey, String actionMsg) { + String query = mSearchAutoComplete.getText().toString(); + Intent intent = createIntent(Intent.ACTION_SEARCH, null, query, null, + actionKey, actionMsg); + launchIntent(intent); + } + + /** + * Launches an intent based on a suggestion. * - * @param jamQuery True means to set the query, false means to reset it to the user's choice + * @param position The index of the suggestion to create the intent from. + * @return true if a successful launch, false if could not (e.g. bad position). */ - private void jamSuggestionQuery(boolean jamQuery, AdapterView<?> parent, int position) { - // quick check against race conditions - if (mSearchable == null) { + protected boolean launchSuggestion(int position) { + return launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null); + } + + /** + * Launches an intent based on a suggestion. + * + * @param position The index of the suggestion to create the intent from. + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or <code>null</code> if none. + * @return true if a successful launch, false if could not (e.g. bad position). + */ + protected boolean launchSuggestion(int position, int actionKey, String actionMsg) { + Cursor c = mSuggestionsAdapter.getCursor(); + if ((c != null) && c.moveToPosition(position)) { + Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg); + launchIntent(intent); + return true; + } + return false; + } + + /** + * Launches an intent. Also dismisses the search dialog if not in global search mode. + */ + private void launchIntent(Intent intent) { + if (intent == null) { return; } - - mSuggestionsAdapter.setNonUserQuery(true); // disables any suggestions processing - if (jamQuery) { - CursorAdapter ca = getSuggestionsAdapter(parent); - Cursor c = ca.getCursor(); - if (c.moveToPosition(position)) { - setupSuggestionIntent(c, mSearchable); - String jamText = null; - - // Simple heuristic for selecting text with which to rewrite the query. - if (mSuggestionQuery != null) { - jamText = mSuggestionQuery; - } else if (mSearchable.mQueryRewriteFromData && (mSuggestionData != null)) { - jamText = mSuggestionData.toString(); - } else if (mSearchable.mQueryRewriteFromText) { - try { - int column = c.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1); - jamText = c.getString(column); - } catch (RuntimeException e) { - // no work here, jamText is null - } - } - if (jamText != null) { - mSearchTextField.setText(jamText); - /* mSearchTextField.selectAll(); */ // this didn't work anyway in the old UI - // TODO this is only needed in the model where we have a selection in the ACTV - // and in the dropdown at the same time. - mSearchTextField.setSelection(jamText.length()); - } - } - } else { - // reset user query - mSearchTextField.setText(mUserQuery); - try { - mSearchTextField.setSelection(mUserQuerySelStart, mUserQuerySelEnd); - } catch (IndexOutOfBoundsException e) { - // In case of error, just select all - Log.e(LOG_TAG, "Caught IndexOutOfBoundsException while setting selection. " + - "start=" + mUserQuerySelStart + " end=" + mUserQuerySelEnd + - " text=\"" + mUserQuery + "\""); - mSearchTextField.selectAll(); - } + if (handleSpecialIntent(intent)){ + return; + } + if (!mGlobalSearchMode) { + dismiss(); } - // TODO because the new query is (not) processed in another thread, we can't just - // take away this flag (yet). The better solution here is going to require a new API - // in AutoCompleteTextView which allows us to change the text w/o changing the suggestions. -// mSuggestionsAdapter.setNonUserQuery(false); + getContext().startActivity(intent); } - + /** - * Assemble a search intent and send it. - * - * @param action The intent to send, typically Intent.ACTION_SEARCH - * @param data The data for the intent - * @param query The user text entered (so far) - * @param appData The app data bundle (if supplied) - * @param actionKey If the intent was triggered by an action key, e.g. KEYCODE_CALL, it will - * be sent here. Pass KeyEvent.KEYCODE_UNKNOWN for no actionKey code. - * @param actionMsg If the intent was triggered by an action key, e.g. KEYCODE_CALL, the - * corresponding tag message will be sent here. Pass null for no actionKey message. - * @param si Reference to the current SearchableInfo. Passed here so it can be used even after - * we've called dismiss(), which attempts to null mSearchable. + * Handles the special intent actions declared in {@link SearchManager}. + * + * @return <code>true</code> if the intent was handled. */ - private void sendLaunchIntent(final String action, final Uri data, final String query, - final Bundle appData, int actionKey, final String actionMsg, final SearchableInfo si) { - Intent launcher = new Intent(action); - - if (query != null) { - launcher.putExtra(SearchManager.QUERY, query); + private boolean handleSpecialIntent(Intent intent) { + String action = intent.getAction(); + if (SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE.equals(action)) { + handleChangeSourceIntent(intent); + return true; + } else if (SearchManager.INTENT_ACTION_CURSOR_RESPOND.equals(action)) { + handleCursorRespondIntent(intent); + return true; } - - if (data != null) { - launcher.setData(data); + return false; + } + + /** + * Handles SearchManager#INTENT_ACTION_CHANGE_SOURCE. + */ + private void handleChangeSourceIntent(Intent intent) { + Uri dataUri = intent.getData(); + if (dataUri == null) { + Log.w(LOG_TAG, "SearchManager.INTENT_ACTION_CHANGE_SOURCE without intent data."); + return; } - - if (appData != null) { - launcher.putExtra(SearchManager.APP_DATA, appData); + ComponentName componentName = ComponentName.unflattenFromString(dataUri.toString()); + if (componentName == null) { + Log.w(LOG_TAG, "Invalid ComponentName: " + dataUri); + return; } - - // add launch info (action key, etc.) - if (actionKey != KeyEvent.KEYCODE_UNKNOWN) { - launcher.putExtra(SearchManager.ACTION_KEY, actionKey); - launcher.putExtra(SearchManager.ACTION_MSG, actionMsg); + if (DBG) Log.d(LOG_TAG, "Switching to " + componentName); + + ComponentName previous = mLaunchComponent; + if (!show(componentName, mAppSearchData, false)) { + Log.w(LOG_TAG, "Failed to switch to source " + componentName); + return; } + pushPreviousComponent(previous); - // attempt to enforce security requirement (no 3rd-party intents) - launcher.setComponent(si.mSearchActivity); - - getContext().startActivity(launcher); + String query = intent.getStringExtra(SearchManager.QUERY); + setUserQuery(query); } - + /** - * Shared code for launching a query from a suggestion. - * @param ca The cursor adapter containing the suggestions - * @param position The suggestion we'll be launching from - * @return true if a successful launch, false if could not (e.g. bad position) + * Handles {@link SearchManager#INTENT_ACTION_CURSOR_RESPOND}. */ - private boolean launchSuggestion(CursorAdapter ca, int position) { - Cursor c = ca.getCursor(); - if ((c != null) && c.moveToPosition(position)) { - setupSuggestionIntent(c, mSearchable); - - final Bundle appData = mAppSearchData; - SearchableInfo si = mSearchable; - String suggestionAction = mSuggestionAction; - Uri suggestionData = mSuggestionData; - String suggestionQuery = mSuggestionQuery; - dismiss(); - sendLaunchIntent(suggestionAction, suggestionData, suggestionQuery, appData, - KeyEvent.KEYCODE_UNKNOWN, null, si); - return true; + private void handleCursorRespondIntent(Intent intent) { + Cursor c = mSuggestionsAdapter.getCursor(); + if (c != null) { + c.respond(intent.getExtras()); } - return false; + } + + /** + * Saves the previous component that was searched, so that we can go + * back to it. + */ + private void pushPreviousComponent(ComponentName componentName) { + if (mPreviousComponents == null) { + mPreviousComponents = new ArrayList<ComponentName>(); + } + mPreviousComponents.add(componentName); + } + + /** + * Pops the previous component off the stack and returns it. + * + * @return The component name, or <code>null</code> if there was + * no previous component. + */ + private ComponentName popPreviousComponent() { + if (mPreviousComponents == null) { + return null; + } + int size = mPreviousComponents.size(); + if (size == 0) { + return null; + } + return mPreviousComponents.remove(size - 1); + } + + /** + * Goes back to the previous component that was searched, if any. + * + * @return <code>true</code> if there was a previous component that we could go back to. + */ + private boolean backToPreviousComponent() { + ComponentName previous = popPreviousComponent(); + if (previous == null) { + return false; + } + if (!show(previous, mAppSearchData, false)) { + Log.w(LOG_TAG, "Failed to switch to source " + previous); + return false; + } + + // must touch text to trigger suggestions + // TODO: should this be the text as it was when the user left + // the source that we are now going back to? + String query = mSearchAutoComplete.getText().toString(); + setUserQuery(query); + + return true; } /** @@ -1159,62 +1169,43 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * and/or falling back to the XML for defaults; It also creates REST style Uri data when * the suggestion includes a data id. * - * NOTE: Return values are in member variables mSuggestionAction & mSuggestionData. - * * @param c The suggestions cursor, moved to the row of the user's selection - * @param si The searchable activity's info record + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or <code>null</code> if none. + * @return An intent for the suggestion at the cursor's position. */ - void setupSuggestionIntent(Cursor c, SearchableInfo si) { + private Intent createIntentFromSuggestion(Cursor c, int actionKey, String actionMsg) { try { // use specific action if supplied, or default action if supplied, or fixed default - mSuggestionAction = null; - int mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_ACTION); - if (mColumn >= 0) { - final String action = c.getString(mColumn); - if (action != null) { - mSuggestionAction = action; - } - } - if (mSuggestionAction == null) { - mSuggestionAction = si.getSuggestIntentAction(); + String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION); + if (action == null) { + action = mSearchable.getSuggestIntentAction(); } - if (mSuggestionAction == null) { - mSuggestionAction = Intent.ACTION_SEARCH; + if (action == null) { + action = Intent.ACTION_SEARCH; } // use specific data if supplied, or default data if supplied - String data = null; - mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA); - if (mColumn >= 0) { - final String rowData = c.getString(mColumn); - if (rowData != null) { - data = rowData; - } - } + String data = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA); if (data == null) { - data = si.getSuggestIntentData(); + data = mSearchable.getSuggestIntentData(); } - // then, if an ID was provided, append it. if (data != null) { - mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); - if (mColumn >= 0) { - final String id = c.getString(mColumn); - if (id != null) { - data = data + "/" + Uri.encode(id); - } + String id = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); + if (id != null) { + data = data + "/" + Uri.encode(id); } } - mSuggestionData = (data == null) ? null : Uri.parse(data); + Uri dataUri = (data == null) ? null : Uri.parse(data); + + String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); - mSuggestionQuery = null; - mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY); - if (mColumn >= 0) { - final String query = c.getString(mColumn); - if (query != null) { - mSuggestionQuery = query; - } - } + String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY); + + return createIntent(action, dataUri, query, extraData, actionKey, actionMsg); } catch (RuntimeException e ) { int rowNum; try { // be really paranoid now @@ -1224,10 +1215,49 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } Log.w(LOG_TAG, "Search Suggestions cursor at row " + rowNum + " returned exception" + e.toString()); + return null; } } /** + * Constructs an intent from the given information and the search dialog state. + * + * @param action Intent action. + * @param data Intent data, or <code>null</code>. + * @param query Intent query, or <code>null</code>. + * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>. + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or <code>null</code> if none. + * @return The intent. + */ + private Intent createIntent(String action, Uri data, String query, String extraData, + int actionKey, String actionMsg) { + // Now build the Intent + Intent intent = new Intent(action); + if (data != null) { + intent.setData(data); + } + if (query != null) { + intent.putExtra(SearchManager.QUERY, query); + } + if (extraData != null) { + intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData); + } + if (mAppSearchData != null) { + intent.putExtra(SearchManager.APP_DATA, mAppSearchData); + } + if (actionKey != KeyEvent.KEYCODE_UNKNOWN) { + intent.putExtra(SearchManager.ACTION_KEY, actionKey); + intent.putExtra(SearchManager.ACTION_MSG, actionMsg); + } + // attempt to enforce security requirement (no 3rd-party intents) + intent.setComponent(mSearchable.mSearchActivity); + return intent; + } + + /** * For a given suggestion and a given cursor row, get the action message. If not provided * by the specific row/column, also check for a single definition (for the action key). * @@ -1236,17 +1266,12 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * * @return Returns a string, or null if no action key message for this suggestion */ - private String getActionKeyMessage(Cursor c, final SearchableInfo.ActionKeyInfo actionKey) { + private static String getActionKeyMessage(Cursor c, SearchableInfo.ActionKeyInfo actionKey) { String result = null; // check first in the cursor data, for a suggestion-specific message final String column = actionKey.mSuggestActionMsgColumn; if (column != null) { - try { - int colId = c.getColumnIndexOrThrow(column); - result = c.getString(colId); - } catch (RuntimeException e) { - // OK - result is already null - } + result = SuggestionsAdapter.getColumnString(c, column); } // If the cursor didn't give us a message, see if there's a single message defined // for the actionkey (for all suggestions) @@ -1257,343 +1282,178 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } /** - * Local subclass for AutoCompleteTextView - * - * This exists entirely to override the threshold method. Otherwise we just use the class - * as-is. + * Local subclass for AutoCompleteTextView. */ public static class SearchAutoComplete extends AutoCompleteTextView { + private int mThreshold; + private SearchDialog mSearchDialog; + public SearchAutoComplete(Context context) { super(null); + mThreshold = getThreshold(); } public SearchAutoComplete(Context context, AttributeSet attrs) { super(context, attrs); + mThreshold = getThreshold(); } public SearchAutoComplete(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + mThreshold = getThreshold(); } - - /** - * We never allow ACTV to automatically replace the text, since we use "jamSuggestionQuery" - * to do that. There's no point in letting ACTV do this here, because in the search UI, - * as soon as we click a suggestion, we're going to start shutting things down. - */ - @Override - public void replaceText(CharSequence text) { + + private void setSearchDialog(SearchDialog searchDialog) { + mSearchDialog = searchDialog; } - /** - * We always return true, so that the effective threshold is "zero". This allows us - * to provide "null" suggestions such as "just show me some recent entries". - */ @Override - public boolean enoughToFilter() { - return true; + public void setThreshold(int threshold) { + super.setThreshold(threshold); + mThreshold = threshold; } - } - - /** - * Support for AutoCompleteTextView-based suggestions - */ - /** - * This class provides the filtering-based interface to suggestions providers. - * It is hardwired in a couple of places to support GoogleSearch - for example, it supports - * two-line suggestions, but it does not support icons. - */ - private static class SuggestionsAdapter extends SimpleCursorAdapter { - private final String TAG = "SuggestionsAdapter"; - - SearchableInfo mSearchable; - private Resources mProviderResources; - - // These private variables are shared by the filter thread and must be protected - private WeakReference<Cursor> mRecentCursor = new WeakReference<Cursor>(null); - private boolean mNonUserQuery = false; - private AutoCompleteTextView mParentView; - public SuggestionsAdapter(Context context, SearchableInfo searchable, - AutoCompleteTextView actv) { - super(context, -1, null, null, null); - mSearchable = searchable; - mParentView = actv; - - // set up provider resources (gives us icons, etc.) - Context activityContext = mSearchable.getActivityContext(mContext); - Context providerContext = mSearchable.getProviderContext(mContext, activityContext); - mProviderResources = providerContext.getResources(); - } - /** - * Set this field (temporarily!) to disable suggestions updating. This allows us - * to change the string in the text view without changing the suggestions list. + * Returns true if the text field is empty, or contains only whitespace. */ - public void setNonUserQuery(boolean nonUserQuery) { - synchronized (this) { - mNonUserQuery = nonUserQuery; - } + private boolean isEmpty() { + return TextUtils.getTrimmedLength(getText()) == 0; } - public boolean getNonUserQuery() { - synchronized (this) { - return mNonUserQuery; - } - } - /** - * Use the search suggestions provider to obtain a live cursor. This will be called - * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions). - * The results will be processed in the UI thread and changeCursor() will be called. - * - * In order to provide the Search Mgr functionality of seeing your query change as you - * scroll through the list, we have to be able to jam new text into the string without - * retriggering the suggestions. We do that here via the "nonUserQuery" flag. In that - * case we simply return the existing cursor. - * - * TODO: Dianne suggests that this should simply be promoted into an AutoCompleteTextView - * behavior (perhaps optionally). - * - * TODO: The "nonuserquery" logic has a race condition because it happens in another thread. - * This also needs to be fixed. + * Clears the entered text. */ - @Override - public Cursor runQueryOnBackgroundThread(CharSequence constraint) { - String query = (constraint == null) ? "" : constraint.toString(); - Cursor c = null; - synchronized (this) { - if (mNonUserQuery) { - c = mRecentCursor.get(); - mNonUserQuery = false; - } - } - if (c == null) { - c = getSuggestions(mSearchable, query); - synchronized (this) { - mRecentCursor = new WeakReference<Cursor>(c); - } - } - return c; + private void clear() { + setText(""); } /** - * Overriding changeCursor() allows us to change not only the cursor, but by sampling - * the cursor's columns, the actual display characteristics of the list. + * We override this method to avoid replacing the query box text + * when a suggestion is clicked. */ @Override - public void changeCursor(Cursor c) { - - // first, check for various conditions that disqualify this cursor - if ((c == null) || (c.getCount() == 0)) { - // no cursor, or cursor with no data - changeCursorAndColumns(null, null, null); - if (c != null) { - c.close(); - } - return; - } - - // check cursor before trying to create list views from it - int colId = c.getColumnIndex("_id"); - int col1 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1); - int col2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2); - int colIc1 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1); - int colIc2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2); - - boolean minimal = (colId >= 0) && (col1 >= 0); - boolean hasIcons = (colIc1 >= 0) && (colIc2 >= 0); - boolean has2Lines = col2 >= 0; - - if (minimal) { - int layout; - String[] from; - int[] to; - - if (hasIcons) { - if (has2Lines) { - layout = com.android.internal.R.layout.search_dropdown_item_icons_2line; - from = TWO_LINE_ICONS_FROM; - to = TWO_LINE_ICONS_TO; - } else { - layout = com.android.internal.R.layout.search_dropdown_item_icons_1line; - from = ONE_LINE_ICONS_FROM; - to = ONE_LINE_ICONS_TO; - } - } else { - if (has2Lines) { - layout = com.android.internal.R.layout.search_dropdown_item_2line; - from = TWO_LINE_FROM; - to = TWO_LINE_TO; - } else { - layout = com.android.internal.R.layout.search_dropdown_item_1line; - from = ONE_LINE_FROM; - to = ONE_LINE_TO; - } - } - // Force the underlying ListView to discard and reload all layouts - // (Note, this should be optimized for cases where layout/cursor remain same) - mParentView.resetListAndClearViews(); - // Now actually set up the cursor, columns, and the list view - changeCursorAndColumns(c, from, to); - setViewResource(layout); - } else { - // Provide some help for developers instead of just silently discarding - Log.w(LOG_TAG, "Suggestions cursor discarded due to missing required columns."); - changeCursorAndColumns(null, null, null); - c.close(); - } - if ((colIc1 >= 0) != (colIc2 >= 0)) { - Log.w(LOG_TAG, "Suggestion icon column(s) discarded, must be 0 or 2 columns."); - } + protected void replaceText(CharSequence text) { } /** - * Overriding this allows us to write the selected query back into the box. - * NOTE: This is a vastly simplified version of SearchDialog.jamQuery() and does - * not universally support the search API. But it is sufficient for Google Search. + * We override this method so that we can allow a threshold of zero, which ACTV does not. */ @Override - public CharSequence convertToString(Cursor cursor) { - CharSequence result = null; - if (cursor != null) { - int column = cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY); - if (column >= 0) { - final String query = cursor.getString(column); - if (query != null) { - result = query; - } - } - } - return result; - } - - /** - * Get the query cursor for the search suggestions. - * - * TODO this is functionally identical to the version in SearchDialog.java. Perhaps it - * could be hoisted into SearchableInfo or some other shared spot. - * - * @param query The search text entered (so far) - * @return Returns a cursor with suggestions, or null if no suggestions - */ - private Cursor getSuggestions(final SearchableInfo searchable, final String query) { - Cursor cursor = null; - if (searchable.getSuggestAuthority() != null) { - try { - StringBuilder uriStr = new StringBuilder("content://"); - uriStr.append(searchable.getSuggestAuthority()); - - // if content path provided, insert it now - final String contentPath = searchable.getSuggestPath(); - if (contentPath != null) { - uriStr.append('/'); - uriStr.append(contentPath); - } - - // append standard suggestion query path - uriStr.append('/' + SearchManager.SUGGEST_URI_PATH_QUERY); - - // inject query, either as selection args or inline - String[] selArgs = null; - if (searchable.getSuggestSelection() != null) { // use selection if provided - selArgs = new String[] {query}; - } else { - uriStr.append('/'); // no sel, use REST pattern - uriStr.append(Uri.encode(query)); - } - - // finally, make the query - cursor = mContext.getContentResolver().query( - Uri.parse(uriStr.toString()), null, - searchable.getSuggestSelection(), selArgs, - null); - } catch (RuntimeException e) { - Log.w(TAG, "Search Suggestions query returned exception " + e.toString()); - cursor = null; - } - } - - return cursor; + public boolean enoughToFilter() { + return mThreshold <= 0 || super.enoughToFilter(); } - + /** - * Overriding this allows us to affect the way that an icon is loaded. Specifically, - * we can be more controlling about the resource path (and allow icons to come from other - * packages). - * - * TODO: This is 100% identical to the version in SearchDialog.java - * - * @param v ImageView to receive an image - * @param value the value retrieved from the cursor + * {@link AutoCompleteTextView#onKeyPreIme(int, KeyEvent)}) dismisses the drop-down on BACK, + * so we must override this method to modify the BACK behavior. */ @Override - public void setViewImage(ImageView v, String value) { - int resID; - Drawable img = null; - - try { - resID = Integer.parseInt(value); - if (resID != 0) { - img = mProviderResources.getDrawable(resID); - } - } catch (NumberFormatException nfe) { - // img = null; - } catch (NotFoundException e2) { - // img = null; - } - - // finally, set the image to whatever we've gotten - v.setImageDrawable(img); + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + return mSearchDialog.handleBackKey(keyCode, event); } - - /** - * This method is overridden purely to provide a bit of protection against - * flaky content providers. - * - * TODO: This is 100% identical to the version in SearchDialog.java - * - * @see android.widget.ListAdapter#getView(int, View, ViewGroup) - */ - @Override - public View getView(int position, View convertView, ViewGroup parent) { - try { - return super.getView(position, convertView, parent); - } catch (RuntimeException e) { - Log.w(TAG, "Search Suggestions cursor returned exception " + e.toString()); - // what can I return here? - View v = newView(mContext, mCursor, parent); - if (v != null) { - TextView tv = (TextView) v.findViewById(com.android.internal.R.id.text1); - tv.setText(e.toString()); - } - return v; + } + + protected boolean handleBackKey(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { + mSearchAutoComplete.dismissDropDown(); + if (backToPreviousComponent()) { + return true; } + if (!mSearchAutoComplete.isEmpty()) { + mSearchAutoComplete.clear(); + return true; + } + cancel(); + return true; } - + return false; } /** * Implements OnItemClickListener */ public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - // Log.d(LOG_TAG, "onItemClick() position " + position); - launchSuggestion(mSuggestionsAdapter, position); + if (DBG) Log.d(LOG_TAG, "onItemClick() position " + position); + launchSuggestion(position); } - + /** * Implements OnItemSelectedListener */ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - // Log.d(LOG_TAG, "onItemSelected() position " + position); - jamSuggestionQuery(true, parent, position); + if (DBG) Log.d(LOG_TAG, "onItemSelected() position " + position); + // A suggestion has been selected, rewrite the query if possible, + // otherwise the restore the original query. + if (REWRITE_QUERIES) { + rewriteQueryFromSuggestion(position); + } } /** * Implements OnItemSelectedListener */ public void onNothingSelected(AdapterView<?> parent) { - // Log.d(LOG_TAG, "onNothingSelected()"); + if (DBG) Log.d(LOG_TAG, "onNothingSelected()"); + } + + /** + * Query rewriting. + */ + + private void rewriteQueryFromSuggestion(int position) { + Cursor c = mSuggestionsAdapter.getCursor(); + if (c == null) { + return; + } + if (c.moveToPosition(position)) { + // Get the new query from the suggestion. + CharSequence newQuery = mSuggestionsAdapter.convertToString(c); + if (newQuery != null) { + // The suggestion rewrites the query. + if (DBG) Log.d(LOG_TAG, "Rewriting query to '" + newQuery + "'"); + // Update the text field, without getting new suggestions. + setQuery(newQuery); + } else { + // The suggestion does not rewrite the query, restore the user's query. + if (DBG) Log.d(LOG_TAG, "Suggestion gives no rewrite, restoring user query."); + restoreUserQuery(); + } + } else { + // We got a bad position, restore the user's query. + Log.w(LOG_TAG, "Bad suggestion position: " + position); + restoreUserQuery(); + } + } + + /** + * Restores the query entered by the user if needed. + */ + private void restoreUserQuery() { + if (DBG) Log.d(LOG_TAG, "Restoring query to '" + mUserQuery + "'"); + setQuery(mUserQuery); + } + + /** + * Sets the text in the query box, without updating the suggestions. + */ + private void setQuery(CharSequence query) { + mSearchAutoComplete.setText(query, false); + if (query != null) { + mSearchAutoComplete.setSelection(query.length()); + } + } + + /** + * Sets the text in the query box, updating the suggestions. + */ + private void setUserQuery(String query) { + if (query == null) { + query = ""; + } + mUserQuery = query; + mSearchAutoComplete.setText(query); + mSearchAutoComplete.setSelection(query.length()); } /** diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index ecdd3f8..3e9f3dd 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -17,12 +17,17 @@ package android.app; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.res.Configuration; +import android.database.Cursor; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.os.RemoteException; import android.os.ServiceManager; +import android.server.search.SearchableInfo; import android.view.KeyEvent; /** @@ -439,20 +444,18 @@ import android.view.KeyEvent; * * <tr><th>{@link #SUGGEST_COLUMN_ICON_1}</th> * <td>If your cursor includes this column, then all suggestions will be provided in an - * icons+text format. This value should be a reference (resource ID) of the icon to + * icons+text format. This value should be a reference to the icon to * draw on the left side, or it can be null or zero to indicate no icon in this row. - * You must provide both cursor columns, or neither. * </td> - * <td align="center">No, but required if you also have {@link #SUGGEST_COLUMN_ICON_2}</td> + * <td align="center">No.</td> * </tr> * * <tr><th>{@link #SUGGEST_COLUMN_ICON_2}</th> * <td>If your cursor includes this column, then all suggestions will be provided in an - * icons+text format. This value should be a reference (resource ID) of the icon to + * icons+text format. This value should be a reference to the icon to * draw on the right side, or it can be null or zero to indicate no icon in this row. - * You must provide both cursor columns, or neither. * </td> - * <td align="center">No, but required if you also have {@link #SUGGEST_COLUMN_ICON_1}</td> + * <td align="center">No.</td> * </tr> * * <tr><th>{@link #SUGGEST_COLUMN_INTENT_ACTION}</th> @@ -1155,6 +1158,13 @@ public class SearchManager public final static String ACTION_KEY = "action_key"; /** + * Intent extra data key: This key will be used for the extra populated by the + * {@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA} column. + * {@hide} + */ + public final static String EXTRA_DATA_KEY = "intent_extra_data_key"; + + /** * Intent extra data key: Use this key with Intent.ACTION_SEARCH and * {@link android.content.Intent#getStringExtra content.Intent.getStringExtra()} * to obtain the action message that was defined for a particular search action key and/or @@ -1195,21 +1205,59 @@ public class SearchManager public final static String SUGGEST_COLUMN_TEXT_2 = "suggest_text_2"; /** * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, - * then all suggestions will be provided in format that includes space for two small icons, + * then all suggestions will be provided in a format that includes space for two small icons, * one at the left and one at the right of each suggestion. The data in the column must - * be a a resource ID for the icon you wish to have displayed. If you include this column, - * you must also include {@link #SUGGEST_COLUMN_ICON_2}. + * be a resource ID of a drawable, or a URI in one of the following formats: + * + * <ul> + * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> + * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li> + * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> + * </ul> + * + * See {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)} + * for more information on these schemes. */ public final static String SUGGEST_COLUMN_ICON_1 = "suggest_icon_1"; /** * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, - * then all suggestions will be provided in format that includes space for two small icons, + * then all suggestions will be provided in a format that includes space for two small icons, * one at the left and one at the right of each suggestion. The data in the column must - * be a a resource ID for the icon you wish to have displayed. If you include this column, - * you must also include {@link #SUGGEST_COLUMN_ICON_1}. + * be a resource ID of a drawable, or a URI in one of the following formats: + * + * <ul> + * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> + * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li> + * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> + * </ul> + * + * See {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)} + * for more information on these schemes. */ public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2"; /** + * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, + * then all suggestions will be provided in a format that includes space for two small icons, + * one at the left and one at the right of each suggestion. The data in the column must + * be a blob that contains a bitmap. + * + * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_1} column. + * + * @hide + */ + public final static String SUGGEST_COLUMN_ICON_1_BITMAP = "suggest_icon_1_bitmap"; + /** + * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, + * then all suggestions will be provided in a format that includes space for two small icons, + * one at the left and one at the right of each suggestion. The data in the column must + * be a blob that contains a bitmap. + * + * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_2} column. + * + * @hide + */ + public final static String SUGGEST_COLUMN_ICON_2_BITMAP = "suggest_icon_2_bitmap"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, this is the action that will be used when * forming the suggestion's intent. If the element is not provided, the action will be taken @@ -1230,6 +1278,14 @@ public class SearchManager */ public final static String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data"; /** + * Column name for suggestions cursor. <i>Optional.</i> This column allows suggestions + * to provide additional arbitrary data which will be included as an extra under the key + * {@link #EXTRA_DATA_KEY}. + * + * @hide pending API council approval + */ + public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, then "/" and this value will be appended to the data * field in the Intent. This should only be used if the data field has already been set to an @@ -1244,6 +1300,54 @@ public class SearchManager */ public final static String SUGGEST_COLUMN_QUERY = "suggest_intent_query"; + /** + * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION}, + * the search dialog will switch to a different suggestion source when the + * suggestion is clicked. + * + * {@link #SUGGEST_COLUMN_INTENT_DATA} must contain + * the flattened {@link ComponentName} of the activity which is to be searched. + * + * TODO: Should {@link #SUGGEST_COLUMN_INTENT_DATA} instead contain a URI in the format + * used by {@link android.provider.Applications}? + * + * TODO: This intent should be protected by the same permission that we use + * for replacing the global search provider. + * + * The query text field will be set to the value of {@link #SUGGEST_COLUMN_QUERY}. + * + * @hide Pending API council approval. + */ + public final static String INTENT_ACTION_CHANGE_SEARCH_SOURCE + = "android.search.action.CHANGE_SEARCH_SOURCE"; + + /** + * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION}, + * the search dialog will call {@link Cursor#respond(Bundle)} when the + * suggestion is clicked. + * + * The {@link Bundle} argument will be constructed + * in the same way as the "extra" bundle included in an Intent constructed + * from the suggestion. + * + * @hide Pending API council approval. + */ + public final static String INTENT_ACTION_CURSOR_RESPOND + = "android.search.action.CURSOR_RESPOND"; + + /** + * Intent action for starting the global search settings activity. + * The global search provider should handle this intent. + * + * @hide Pending API council approval. + */ + public final static String INTENT_ACTION_SEARCH_SETTINGS + = "android.search.action.SEARCH_SETTINGS"; + + /** + * Reference to the shared system search service. + */ + private static ISearchManager sService = getSearchManagerService(); private final Context mContext; private final Handler mHandler; @@ -1257,12 +1361,6 @@ public class SearchManager mContext = context; mHandler = handler; } - private static ISearchManager mService; - - static { - mService = ISearchManager.Stub.asInterface( - ServiceManager.getService(Context.SEARCH_SERVICE)); - } /** * Launch search UI. @@ -1459,5 +1557,93 @@ public class SearchManager mSearchDialog.onConfigurationChanged(newConfig); } } - + + private static ISearchManager getSearchManagerService() { + return ISearchManager.Stub.asInterface( + ServiceManager.getService(Context.SEARCH_SERVICE)); + } + + /** + * Gets information about a searchable activity. This method is static so that it can + * be used from non-Activity contexts. + * + * @param componentName The activity to get searchable information for. + * @param globalSearch If <code>false</code>, return information about the given activity. + * If <code>true</code>, return information about the global search activity. + * @return Searchable information, or <code>null</code> if the activity is not searchable. + * + * @hide because SearchableInfo is not part of the API. + */ + public static SearchableInfo getSearchableInfo(ComponentName componentName, + boolean globalSearch) { + try { + return sService.getSearchableInfo(componentName, globalSearch); + } catch (RemoteException e) { + return null; + } + } + + /** + * Checks whether the given searchable is the default searchable. + * + * @hide because SearchableInfo is not part of the API. + */ + public static boolean isDefaultSearchable(SearchableInfo searchable) { + SearchableInfo defaultSearchable = SearchManager.getSearchableInfo(null, true); + return defaultSearchable != null + && defaultSearchable.mSearchActivity.equals(searchable.mSearchActivity); + } + + /** + * Gets a cursor with search suggestions. This method is static so that it can + * be used from non-Activity context. + * + * @param searchable Information about how to get the suggestions. + * @param query The search text entered (so far). + * @return a cursor with suggestions, or <code>null</null> the suggestion query failed. + * + * @hide because SearchableInfo is not part of the API. + */ + public static Cursor getSuggestions(Context context, SearchableInfo searchable, String query) { + if (searchable == null) { + return null; + } + + String authority = searchable.getSuggestAuthority(); + if (authority == null) { + return null; + } + + Uri.Builder uriBuilder = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(authority); + + // if content path provided, insert it now + final String contentPath = searchable.getSuggestPath(); + if (contentPath != null) { + uriBuilder.appendEncodedPath(contentPath); + } + + // append standard suggestion query path + uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); + + // get the query selection, may be null + String selection = searchable.getSuggestSelection(); + // inject query, either as selection args or inline + String[] selArgs = null; + if (selection != null) { // use selection if provided + selArgs = new String[] { query }; + } else { // no selection, use REST pattern + uriBuilder.appendPath(query); + } + + Uri uri = uriBuilder + .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() + .fragment("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() + .build(); + + // finally, make the query + return context.getContentResolver().query(uri, null, selection, selArgs, null); + } + } diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java new file mode 100644 index 0000000..af2a321 --- /dev/null +++ b/core/java/android/app/SuggestionsAdapter.java @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2009 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 android.app; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.res.Resources.NotFoundException; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.server.search.SearchableInfo; +import android.text.Html; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; +import android.widget.ImageView; +import android.widget.ResourceCursorAdapter; +import android.widget.TextView; + +import java.io.FileNotFoundException; +import java.util.WeakHashMap; + +/** + * Provides the contents for the suggestion drop-down list.in {@link SearchDialog}. + * + * @hide + */ +class SuggestionsAdapter extends ResourceCursorAdapter { + private static final boolean DBG = false; + private static final String LOG_TAG = "SuggestionsAdapter"; + + private SearchableInfo mSearchable; + private Context mProviderContext; + private WeakHashMap<String, Drawable> mOutsideDrawablesCache; + + // Cached column indexes, updated when the cursor changes. + private int mFormatCol; + private int mText1Col; + private int mText2Col; + private int mIconName1Col; + private int mIconName2Col; + private int mIconBitmap1Col; + private int mIconBitmap2Col; + + public SuggestionsAdapter(Context context, SearchableInfo searchable, + WeakHashMap<String, Drawable> outsideDrawablesCache) { + super(context, + com.android.internal.R.layout.search_dropdown_item_icons_2line, + null, // no initial cursor + true); // auto-requery + mSearchable = searchable; + + // set up provider resources (gives us icons, etc.) + Context activityContext = mSearchable.getActivityContext(mContext); + mProviderContext = mSearchable.getProviderContext(mContext, activityContext); + + mOutsideDrawablesCache = outsideDrawablesCache; + } + + /** + * Overridden to always return <code>false</code>, since we cannot be sure that + * suggestion sources return stable IDs. + */ + @Override + public boolean hasStableIds() { + return false; + } + + /** + * Use the search suggestions provider to obtain a live cursor. This will be called + * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions). + * The results will be processed in the UI thread and changeCursor() will be called. + */ + @Override + public Cursor runQueryOnBackgroundThread(CharSequence constraint) { + if (DBG) Log.d(LOG_TAG, "runQueryOnBackgroundThread(" + constraint + ")"); + String query = (constraint == null) ? "" : constraint.toString(); + try { + return SearchManager.getSuggestions(mContext, mSearchable, query); + } catch (RuntimeException e) { + Log.w(LOG_TAG, "Search suggestions query threw an exception.", e); + return null; + } + } + + /** + * Cache columns. + */ + @Override + public void changeCursor(Cursor c) { + if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")"); + super.changeCursor(c); + if (c != null) { + mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT); + mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1); + mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2); + mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1); + mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2); + mIconBitmap1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1_BITMAP); + mIconBitmap2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2_BITMAP); + } + } + + /** + * Tags the view with cached child view look-ups. + */ + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + View v = super.newView(context, cursor, parent); + v.setTag(new ChildViewCache(v)); + return v; + } + + /** + * Cache of the child views of drop-drown list items, to avoid looking up the children + * each time the contents of a list item are changed. + */ + private final static class ChildViewCache { + public final TextView mText1; + public final TextView mText2; + public final ImageView mIcon1; + public final ImageView mIcon2; + + public ChildViewCache(View v) { + mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1); + mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2); + mIcon1 = (ImageView) v.findViewById(com.android.internal.R.id.icon1); + mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2); + } + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + ChildViewCache views = (ChildViewCache) view.getTag(); + boolean isHtml = false; + if (mFormatCol >= 0) { + String format = cursor.getString(mFormatCol); + isHtml = "html".equals(format); + } + setViewText(cursor, views.mText1, mText1Col, isHtml); + setViewText(cursor, views.mText2, mText2Col, isHtml); + setViewIcon(cursor, views.mIcon1, mIconBitmap1Col, mIconName1Col); + setViewIcon(cursor, views.mIcon2, mIconBitmap2Col, mIconName2Col); + } + + private void setViewText(Cursor cursor, TextView v, int textCol, boolean isHtml) { + if (v == null) { + return; + } + CharSequence text = null; + if (textCol >= 0) { + String str = cursor.getString(textCol); + text = (str != null && isHtml) ? Html.fromHtml(str) : str; + } + // Set the text even if it's null, since we need to clear any previous text. + v.setText(text); + + if (TextUtils.isEmpty(text)) { + v.setVisibility(View.GONE); + } else { + v.setVisibility(View.VISIBLE); + } + } + + private void setViewIcon(Cursor cursor, ImageView v, int iconBitmapCol, int iconNameCol) { + if (v == null) { + return; + } + Drawable drawable = null; + // First try the bitmap column + if (iconBitmapCol >= 0) { + byte[] data = cursor.getBlob(iconBitmapCol); + if (data != null) { + Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); + if (bitmap != null) { + drawable = new BitmapDrawable(bitmap); + } + } + } + // If there was no bitmap, try the icon resource column. + if (drawable == null && iconNameCol >= 0) { + String value = cursor.getString(iconNameCol); + drawable = getDrawableFromResourceValue(value); + } + // Set the icon even if the drawable is null, since we need to clear any + // previous icon. + v.setImageDrawable(drawable); + + if (drawable == null) { + v.setVisibility(View.GONE); + } else { + v.setVisibility(View.VISIBLE); + } + } + + /** + * Gets the text to show in the query field when a suggestion is selected. + * + * @param cursor The Cursor to read the suggestion data from. The Cursor should already + * be moved to the suggestion that is to be read from. + * @return The text to show, or <code>null</code> if the query should not be + * changed when selecting this suggestion. + */ + @Override + public CharSequence convertToString(Cursor cursor) { + if (cursor == null) { + return null; + } + + String query = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_QUERY); + if (query != null) { + return query; + } + + if (mSearchable.mQueryRewriteFromData) { + String data = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_INTENT_DATA); + if (data != null) { + return data; + } + } + + if (mSearchable.mQueryRewriteFromText) { + String text1 = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_TEXT_1); + if (text1 != null) { + return text1; + } + } + + return null; + } + + /** + * This method is overridden purely to provide a bit of protection against + * flaky content providers. + * + * @see android.widget.ListAdapter#getView(int, View, ViewGroup) + */ + @Override + public View getView(int position, View convertView, ViewGroup parent) { + try { + return super.getView(position, convertView, parent); + } catch (RuntimeException e) { + Log.w(LOG_TAG, "Search suggestions cursor threw exception.", e); + // Put exception string in item title + View v = newView(mContext, mCursor, parent); + if (v != null) { + ChildViewCache views = (ChildViewCache) v.getTag(); + TextView tv = views.mText1; + tv.setText(e.toString()); + } + return v; + } + } + + /** + * Gets a drawable given a value provided by a suggestion provider. + * + * This value could be just the string value of a resource id + * (e.g., "2130837524"), in which case we will try to retrieve a drawable from + * the provider's resources. If the value is not an integer, it is + * treated as a Uri and opened with + * {@link ContentResolver#openOutputStream(android.net.Uri, String)}. + * + * All resources and URIs are read using the suggestion provider's context. + * + * If the string is not formatted as expected, or no drawable can be found for + * the provided value, this method returns null. + * + * @param drawableId a string like "2130837524", + * "android.resource://com.android.alarmclock/2130837524", + * or "content://contacts/photos/253". + * @return a Drawable, or null if none found + */ + private Drawable getDrawableFromResourceValue(String drawableId) { + if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) { + return null; + } + + // First, check the cache. + Drawable drawable = mOutsideDrawablesCache.get(drawableId); + if (drawable != null) return drawable; + + try { + // Not cached, try using it as a plain resource ID in the provider's context. + int resourceId = Integer.parseInt(drawableId); + drawable = mProviderContext.getResources().getDrawable(resourceId); + } catch (NumberFormatException nfe) { + // The id was not an integer resource id. + // Let the ContentResolver handle content, android.resource and file URIs. + try { + Uri uri = Uri.parse(drawableId); + drawable = Drawable.createFromStream( + mProviderContext.getContentResolver().openInputStream(uri), + null); + } catch (FileNotFoundException fnfe) { + // drawable = null; + } + + // If we got a drawable for this resource id, then stick it in the + // map so we don't do this lookup again. + if (drawable != null) { + mOutsideDrawablesCache.put(drawableId, drawable); + } + } catch (NotFoundException nfe) { + // Resource could not be found + // drawable = null; + } + + return drawable; + } + + /** + * Gets the value of a string column by name. + * + * @param cursor Cursor to read the value from. + * @param columnName The name of the column to read. + * @return The value of the given column, or <code>null</null> + * if the cursor does not contain the given column. + */ + public static String getColumnString(Cursor cursor, String columnName) { + int col = cursor.getColumnIndex(columnName); + if (col == -1) { + return null; + } + return cursor.getString(col); + } + +} diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index e82a86c..b3e81d7 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -4390,12 +4390,35 @@ public class Intent implements Parcelable { @Override public String toString() { - StringBuilder b = new StringBuilder(); + StringBuilder b = new StringBuilder(128); - b.append("Intent {"); - if (mAction != null) b.append(" action=").append(mAction); + b.append("Intent { "); + toShortString(b, true, true); + b.append(" }"); + + return b.toString(); + } + + /** @hide */ + public String toShortString(boolean comp, boolean extras) { + StringBuilder b = new StringBuilder(128); + toShortString(b, comp, extras); + return b.toString(); + } + + /** @hide */ + public void toShortString(StringBuilder b, boolean comp, boolean extras) { + boolean first = true; + if (mAction != null) { + b.append("act=").append(mAction); + first = false; + } if (mCategories != null) { - b.append(" categories={"); + if (!first) { + b.append(' '); + } + first = false; + b.append("cat=["); Iterator<String> i = mCategories.iterator(); boolean didone = false; while (i.hasNext()) { @@ -4403,20 +4426,48 @@ public class Intent implements Parcelable { didone = true; b.append(i.next()); } - b.append("}"); + b.append("]"); + } + if (mData != null) { + if (!first) { + b.append(' '); + } + first = false; + b.append("dat=").append(mData); + } + if (mType != null) { + if (!first) { + b.append(' '); + } + first = false; + b.append("typ=").append(mType); + } + if (mFlags != 0) { + if (!first) { + b.append(' '); + } + first = false; + b.append("flg=0x").append(Integer.toHexString(mFlags)); + } + if (comp && mComponent != null) { + if (!first) { + b.append(' '); + } + first = false; + b.append("cmp=").append(mComponent.flattenToShortString()); + } + if (extras && mExtras != null) { + if (!first) { + b.append(' '); + } + first = false; + b.append("(has extras)"); } - if (mData != null) b.append(" data=").append(mData); - if (mType != null) b.append(" type=").append(mType); - if (mFlags != 0) b.append(" flags=0x").append(Integer.toHexString(mFlags)); - if (mComponent != null) b.append(" comp=").append(mComponent.toShortString()); - if (mExtras != null) b.append(" (has extras)"); - b.append(" }"); - - return b.toString(); } public String toURI() { - StringBuilder uri = new StringBuilder(mData != null ? mData.toString() : ""); + StringBuilder uri = new StringBuilder(128); + if (mData != null) uri.append(mData.toString()); uri.append("#Intent;"); diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 9b190df..e5c5dc8 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -1254,47 +1254,71 @@ public class IntentFilter implements Parcelable { } public void dump(Printer du, String prefix) { + StringBuilder sb = new StringBuilder(256); if (mActions.size() > 0) { Iterator<String> it = mActions.iterator(); while (it.hasNext()) { - du.println(prefix + "Action: \"" + it.next() + "\""); + sb.setLength(0); + sb.append(prefix); sb.append("Action: \""); + sb.append(it.next()); sb.append("\""); + du.println(sb.toString()); } } if (mCategories != null) { Iterator<String> it = mCategories.iterator(); while (it.hasNext()) { - du.println(prefix + "Category: \"" + it.next() + "\""); + sb.setLength(0); + sb.append(prefix); sb.append("Category: \""); + sb.append(it.next()); sb.append("\""); + du.println(sb.toString()); } } if (mDataSchemes != null) { Iterator<String> it = mDataSchemes.iterator(); while (it.hasNext()) { - du.println(prefix + "Data Scheme: \"" + it.next() + "\""); + sb.setLength(0); + sb.append(prefix); sb.append("Scheme: \""); + sb.append(it.next()); sb.append("\""); + du.println(sb.toString()); } } if (mDataAuthorities != null) { Iterator<AuthorityEntry> it = mDataAuthorities.iterator(); while (it.hasNext()) { AuthorityEntry ae = it.next(); - du.println(prefix + "Data Authority: \"" + ae.mHost + "\":" - + ae.mPort + (ae.mWild ? " WILD" : "")); + sb.setLength(0); + sb.append(prefix); sb.append("Authority: \""); + sb.append(ae.mHost); sb.append("\": "); + sb.append(ae.mPort); + if (ae.mWild) sb.append(" WILD"); + du.println(sb.toString()); } } if (mDataPaths != null) { Iterator<PatternMatcher> it = mDataPaths.iterator(); while (it.hasNext()) { PatternMatcher pe = it.next(); - du.println(prefix + "Data Path: \"" + pe + "\""); + sb.setLength(0); + sb.append(prefix); sb.append("Path: \""); + sb.append(pe); sb.append("\""); + du.println(sb.toString()); } } if (mDataTypes != null) { Iterator<String> it = mDataTypes.iterator(); while (it.hasNext()) { - du.println(prefix + "Data Type: \"" + it.next() + "\""); + sb.setLength(0); + sb.append(prefix); sb.append("Type: \""); + sb.append(it.next()); sb.append("\""); + du.println(sb.toString()); } } - du.println(prefix + "mPriority=" + mPriority - + ", mHasPartialTypes=" + mHasPartialTypes); + if (mPriority != 0 || mHasPartialTypes) { + sb.setLength(0); + sb.append(prefix); sb.append("mPriority="); sb.append(mPriority); + sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes); + du.println(sb.toString()); + } } public static final Parcelable.Creator<IntentFilter> CREATOR diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 2dcb483..963d311 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -64,6 +64,48 @@ public class PackageParser { private static final Object mSync = new Object(); private static WeakReference<byte[]> mReadBuffer; + static class ParsePackageItemArgs { + final Package owner; + final String[] outError; + final int nameRes; + final int labelRes; + final int iconRes; + + String tag; + TypedArray sa; + + ParsePackageItemArgs(Package _owner, String[] _outError, + int _nameRes, int _labelRes, int _iconRes) { + owner = _owner; + outError = _outError; + nameRes = _nameRes; + labelRes = _labelRes; + iconRes = _iconRes; + } + } + + static class ParseComponentArgs extends ParsePackageItemArgs { + final String[] sepProcesses; + final int processRes; + final int enabledRes; + int flags; + + ParseComponentArgs(Package _owner, String[] _outError, + int _nameRes, int _labelRes, int _iconRes, + String[] _sepProcesses, int _processRes,int _enabledRes) { + super(_owner, _outError, _nameRes, _labelRes, _iconRes); + sepProcesses = _sepProcesses; + processRes = _processRes; + enabledRes = _enabledRes; + } + } + + private ParsePackageItemArgs mParseInstrumentationArgs; + private ParseComponentArgs mParseActivityArgs; + private ParseComponentArgs mParseActivityAliasArgs; + private ParseComponentArgs mParseServiceArgs; + private ParseComponentArgs mParseProviderArgs; + /** If set to true, we will only allow package files that exactly match * the DTD. Otherwise, we try to get as much from the package as we * can without failing. This should normally be set to false, to @@ -557,6 +599,11 @@ public class PackageParser { throws XmlPullParserException, IOException { AttributeSet attrs = parser; + mParseInstrumentationArgs = null; + mParseActivityArgs = null; + mParseServiceArgs = null; + mParseProviderArgs = null; + String pkgName = parsePackageName(parser, attrs, flags, outError); if (pkgName == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; @@ -593,8 +640,6 @@ public class PackageParser { } sa.recycle(); - final int innerDepth = parser.getDepth(); - int outerDepth = parser.getDepth(); while ((type=parser.next()) != parser.END_DOCUMENT && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { @@ -950,20 +995,24 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestInstrumentation); - Instrumentation a = new Instrumentation(owner); - - if (!parsePackageItemInfo(owner, a.info, outError, "<instrumentation>", sa, - com.android.internal.R.styleable.AndroidManifestInstrumentation_name, - com.android.internal.R.styleable.AndroidManifestInstrumentation_label, - com.android.internal.R.styleable.AndroidManifestInstrumentation_icon)) { + if (mParseInstrumentationArgs == null) { + mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError, + com.android.internal.R.styleable.AndroidManifestInstrumentation_name, + com.android.internal.R.styleable.AndroidManifestInstrumentation_label, + com.android.internal.R.styleable.AndroidManifestInstrumentation_icon); + mParseInstrumentationArgs.tag = "<instrumentation>"; + } + + mParseInstrumentationArgs.sa = sa; + + Instrumentation a = new Instrumentation(mParseInstrumentationArgs, + new InstrumentationInfo()); + if (outError[0] != null) { sa.recycle(); mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return null; } - a.component = new ComponentName(owner.applicationInfo.packageName, - a.info.name); - String str; str = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage); @@ -1140,7 +1189,7 @@ public class PackageParser { owner.providers.add(p); } else if (tagName.equals("activity-alias")) { - Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError, false); + Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError); if (a == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; @@ -1239,22 +1288,29 @@ public class PackageParser { return outError[0] == null; } - + private Activity parseActivity(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError, boolean receiver) throws XmlPullParserException, IOException { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestActivity); - Activity a = new Activity(owner); - - if (!parseComponentInfo(owner, flags, a.info, outError, - receiver ? "<receiver>" : "<activity>", sa, - com.android.internal.R.styleable.AndroidManifestActivity_name, - com.android.internal.R.styleable.AndroidManifestActivity_label, - com.android.internal.R.styleable.AndroidManifestActivity_icon, - com.android.internal.R.styleable.AndroidManifestActivity_process, - com.android.internal.R.styleable.AndroidManifestActivity_enabled)) { + if (mParseActivityArgs == null) { + mParseActivityArgs = new ParseComponentArgs(owner, outError, + com.android.internal.R.styleable.AndroidManifestActivity_name, + com.android.internal.R.styleable.AndroidManifestActivity_label, + com.android.internal.R.styleable.AndroidManifestActivity_icon, + mSeparateProcesses, + com.android.internal.R.styleable.AndroidManifestActivity_process, + com.android.internal.R.styleable.AndroidManifestActivity_enabled); + } + + mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>"; + mParseActivityArgs.sa = sa; + mParseActivityArgs.flags = flags; + + Activity a = new Activity(mParseActivityArgs, new ActivityInfo()); + if (outError[0] != null) { sa.recycle(); return null; } @@ -1266,9 +1322,6 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestActivity_exported, false); } - a.component = new ComponentName(owner.applicationInfo.packageName, - a.info.name); - a.info.theme = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestActivity_theme, 0); @@ -1412,8 +1465,8 @@ public class PackageParser { } private Activity parseActivityAlias(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, int flags, String[] outError, - boolean receiver) throws XmlPullParserException, IOException { + XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) + throws XmlPullParserException, IOException { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestActivityAlias); @@ -1432,7 +1485,20 @@ public class PackageParser { return null; } - Activity a = new Activity(owner); + if (mParseActivityAliasArgs == null) { + mParseActivityAliasArgs = new ParseComponentArgs(owner, outError, + com.android.internal.R.styleable.AndroidManifestActivityAlias_name, + com.android.internal.R.styleable.AndroidManifestActivityAlias_label, + com.android.internal.R.styleable.AndroidManifestActivityAlias_icon, + mSeparateProcesses, + 0, + com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled); + mParseActivityAliasArgs.tag = "<activity-alias>"; + } + + mParseActivityAliasArgs.sa = sa; + mParseActivityAliasArgs.flags = flags; + Activity target = null; final int NA = owner.activities.size(); @@ -1451,26 +1517,21 @@ public class PackageParser { return null; } - a.info.targetActivity = targetActivity; - - a.info.configChanges = target.info.configChanges; - a.info.flags = target.info.flags; - a.info.icon = target.info.icon; - a.info.labelRes = target.info.labelRes; - a.info.launchMode = target.info.launchMode; - a.info.nonLocalizedLabel = target.info.nonLocalizedLabel; - a.info.processName = target.info.processName; - a.info.screenOrientation = target.info.screenOrientation; - a.info.taskAffinity = target.info.taskAffinity; - a.info.theme = target.info.theme; - - if (!parseComponentInfo(owner, flags, a.info, outError, - receiver ? "<receiver>" : "<activity>", sa, - com.android.internal.R.styleable.AndroidManifestActivityAlias_name, - com.android.internal.R.styleable.AndroidManifestActivityAlias_label, - com.android.internal.R.styleable.AndroidManifestActivityAlias_icon, - 0, - com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled)) { + ActivityInfo info = new ActivityInfo(); + info.targetActivity = targetActivity; + info.configChanges = target.info.configChanges; + info.flags = target.info.flags; + info.icon = target.info.icon; + info.labelRes = target.info.labelRes; + info.nonLocalizedLabel = target.info.nonLocalizedLabel; + info.launchMode = target.info.launchMode; + info.processName = target.info.processName; + info.screenOrientation = target.info.screenOrientation; + info.taskAffinity = target.info.taskAffinity; + info.theme = target.info.theme; + + Activity a = new Activity(mParseActivityAliasArgs, info); + if (outError[0] != null) { sa.recycle(); return null; } @@ -1482,9 +1543,6 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false); } - a.component = new ComponentName(owner.applicationInfo.packageName, - a.info.name); - String str; str = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestActivityAlias_permission); @@ -1548,14 +1606,22 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestProvider); - Provider p = new Provider(owner); - - if (!parseComponentInfo(owner, flags, p.info, outError, "<provider>", sa, - com.android.internal.R.styleable.AndroidManifestProvider_name, - com.android.internal.R.styleable.AndroidManifestProvider_label, - com.android.internal.R.styleable.AndroidManifestProvider_icon, - com.android.internal.R.styleable.AndroidManifestProvider_process, - com.android.internal.R.styleable.AndroidManifestProvider_enabled)) { + if (mParseProviderArgs == null) { + mParseProviderArgs = new ParseComponentArgs(owner, outError, + com.android.internal.R.styleable.AndroidManifestProvider_name, + com.android.internal.R.styleable.AndroidManifestProvider_label, + com.android.internal.R.styleable.AndroidManifestProvider_icon, + mSeparateProcesses, + com.android.internal.R.styleable.AndroidManifestProvider_process, + com.android.internal.R.styleable.AndroidManifestProvider_enabled); + mParseProviderArgs.tag = "<provider>"; + } + + mParseProviderArgs.sa = sa; + mParseProviderArgs.flags = flags; + + Provider p = new Provider(mParseProviderArgs, new ProviderInfo()); + if (outError[0] != null) { sa.recycle(); return null; } @@ -1563,9 +1629,6 @@ public class PackageParser { p.info.exported = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestProvider_exported, true); - p.component = new ComponentName(owner.applicationInfo.packageName, - p.info.name); - String cpname = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestProvider_authorities); @@ -1706,14 +1769,22 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestService); - Service s = new Service(owner); - - if (!parseComponentInfo(owner, flags, s.info, outError, "<service>", sa, - com.android.internal.R.styleable.AndroidManifestService_name, - com.android.internal.R.styleable.AndroidManifestService_label, - com.android.internal.R.styleable.AndroidManifestService_icon, - com.android.internal.R.styleable.AndroidManifestService_process, - com.android.internal.R.styleable.AndroidManifestService_enabled)) { + if (mParseServiceArgs == null) { + mParseServiceArgs = new ParseComponentArgs(owner, outError, + com.android.internal.R.styleable.AndroidManifestService_name, + com.android.internal.R.styleable.AndroidManifestService_label, + com.android.internal.R.styleable.AndroidManifestService_icon, + mSeparateProcesses, + com.android.internal.R.styleable.AndroidManifestService_process, + com.android.internal.R.styleable.AndroidManifestService_enabled); + mParseServiceArgs.tag = "<service>"; + } + + mParseServiceArgs.sa = sa; + mParseServiceArgs.flags = flags; + + Service s = new Service(mParseServiceArgs, new ServiceInfo()); + if (outError[0] != null) { sa.recycle(); return null; } @@ -1725,9 +1796,6 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestService_exported, false); } - s.component = new ComponentName(owner.applicationInfo.packageName, - s.info.name); - String str = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestService_permission); if (str == null) { @@ -2084,16 +2152,75 @@ public class PackageParser { public static class Component<II extends IntentInfo> { public final Package owner; - public final ArrayList<II> intents = new ArrayList<II>(0); - public ComponentName component; + public final ArrayList<II> intents; + public final ComponentName component; + public final String componentShortName; public Bundle metaData; public Component(Package _owner) { owner = _owner; + intents = null; + component = null; + componentShortName = null; + } + + public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) { + owner = args.owner; + intents = new ArrayList<II>(0); + String name = args.sa.getNonResourceString(args.nameRes); + if (name == null) { + component = null; + componentShortName = null; + args.outError[0] = args.tag + " does not specify android:name"; + return; + } + + outInfo.name + = buildClassName(owner.applicationInfo.packageName, name, args.outError); + if (outInfo.name == null) { + component = null; + componentShortName = null; + args.outError[0] = args.tag + " does not have valid android:name"; + return; + } + + component = new ComponentName(owner.applicationInfo.packageName, + outInfo.name); + componentShortName = component.flattenToShortString(); + + int iconVal = args.sa.getResourceId(args.iconRes, 0); + if (iconVal != 0) { + outInfo.icon = iconVal; + outInfo.nonLocalizedLabel = null; + } + + TypedValue v = args.sa.peekValue(args.labelRes); + if (v != null && (outInfo.labelRes=v.resourceId) == 0) { + outInfo.nonLocalizedLabel = v.coerceToString(); + } + + outInfo.packageName = owner.packageName; + } + + public Component(final ParseComponentArgs args, final ComponentInfo outInfo) { + this(args, (PackageItemInfo)outInfo); + if (args.outError[0] != null) { + return; + } + + if (args.processRes != 0) { + outInfo.processName = buildProcessName(owner.applicationInfo.packageName, + owner.applicationInfo.processName, args.sa.getNonResourceString(args.processRes), + args.flags, args.sepProcesses, args.outError); + } + outInfo.enabled = args.sa.getBoolean(args.enabledRes, true); } public Component(Component<II> clone) { owner = clone.owner; + intents = clone.intents; + component = clone.component; + componentShortName = clone.componentShortName; metaData = clone.metaData; } } @@ -2192,14 +2319,14 @@ public class PackageParser { } public final static class Activity extends Component<ActivityIntentInfo> { - public final ActivityInfo info = - new ActivityInfo(); + public final ActivityInfo info; - public Activity(Package _owner) { - super(_owner); - info.applicationInfo = owner.applicationInfo; + public Activity(final ParseComponentArgs args, final ActivityInfo _info) { + super(args, _info); + info = _info; + info.applicationInfo = args.owner.applicationInfo; } - + public String toString() { return "Activity{" + Integer.toHexString(System.identityHashCode(this)) @@ -2221,14 +2348,14 @@ public class PackageParser { } public final static class Service extends Component<ServiceIntentInfo> { - public final ServiceInfo info = - new ServiceInfo(); + public final ServiceInfo info; - public Service(Package _owner) { - super(_owner); - info.applicationInfo = owner.applicationInfo; + public Service(final ParseComponentArgs args, final ServiceInfo _info) { + super(args, _info); + info = _info; + info.applicationInfo = args.owner.applicationInfo; } - + public String toString() { return "Service{" + Integer.toHexString(System.identityHashCode(this)) @@ -2252,13 +2379,13 @@ public class PackageParser { public final ProviderInfo info; public boolean syncable; - public Provider(Package _owner) { - super(_owner); - info = new ProviderInfo(); - info.applicationInfo = owner.applicationInfo; + public Provider(final ParseComponentArgs args, final ProviderInfo _info) { + super(args, _info); + info = _info; + info.applicationInfo = args.owner.applicationInfo; syncable = false; } - + public Provider(Provider existingProvider) { super(existingProvider); this.info = existingProvider.info; @@ -2291,13 +2418,13 @@ public class PackageParser { } public final static class Instrumentation extends Component { - public final InstrumentationInfo info = - new InstrumentationInfo(); + public final InstrumentationInfo info; - public Instrumentation(Package _owner) { - super(_owner); + public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) { + super(args, _info); + info = _info; } - + public String toString() { return "Instrumentation{" + Integer.toHexString(System.identityHashCode(this)) diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 956b15a..bb3486c 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -144,11 +144,29 @@ public final class Configuration implements Parcelable, Comparable<Configuration } public String toString() { - return "{ scale=" + fontScale + " imsi=" + mcc + "/" + mnc - + " locale=" + locale - + " touch=" + touchscreen + " key=" + keyboard + "/" - + keyboardHidden + "/" + hardKeyboardHidden - + " nav=" + navigation + " orien=" + orientation + " }"; + StringBuilder sb = new StringBuilder(128); + sb.append("{ scale="); + sb.append(fontScale); + sb.append(" imsi="); + sb.append(mcc); + sb.append("/"); + sb.append(mnc); + sb.append(" loc="); + sb.append(locale); + sb.append(" touch="); + sb.append(touchscreen); + sb.append(" keys="); + sb.append(keyboard); + sb.append("/"); + sb.append(keyboardHidden); + sb.append("/"); + sb.append(hardKeyboardHidden); + sb.append(" nav="); + sb.append(navigation); + sb.append(" orien="); + sb.append(orientation); + sb.append('}'); + return sb.toString(); } /** diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 39d36de..333ba73 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -113,7 +113,7 @@ public abstract class BatteryStats implements Parcelable { private static final String DATA_CONNECTION_TIME_DATA = "dct"; private static final String DATA_CONNECTION_COUNT_DATA = "dcc"; - private final StringBuilder mFormatBuilder = new StringBuilder(8); + private final StringBuilder mFormatBuilder = new StringBuilder(32); private final Formatter mFormatter = new Formatter(mFormatBuilder); /** @@ -522,7 +522,7 @@ public abstract class BatteryStats implements Parcelable { public abstract Map<String, ? extends Timer> getKernelWakelockStats(); - private final static void formatTime(StringBuilder out, long seconds) { + private final static void formatTimeRaw(StringBuilder out, long seconds) { long days = seconds / (60 * 60 * 24); if (days != 0) { out.append(days); @@ -550,22 +550,18 @@ public abstract class BatteryStats implements Parcelable { } } - private final static String formatTime(long time) { + private final static void formatTime(StringBuilder sb, long time) { long sec = time / 100; - StringBuilder sb = new StringBuilder(); - formatTime(sb, sec); + formatTimeRaw(sb, sec); sb.append((time - (sec * 100)) * 10); sb.append("ms "); - return sb.toString(); } - private final static String formatTimeMs(long time) { + private final static void formatTimeMs(StringBuilder sb, long time) { long sec = time / 1000; - StringBuilder sb = new StringBuilder(); - formatTime(sb, sec); + formatTimeRaw(sb, sec); sb.append(time - (sec * 1000)); sb.append("ms "); - return sb.toString(); } private final String formatRatioLocked(long num, long den) { @@ -616,8 +612,8 @@ public abstract class BatteryStats implements Parcelable { int count = timer.getCountLocked(which); if (totalTimeMillis != 0) { sb.append(linePrefix); - sb.append(formatTimeMs(totalTimeMillis)); - sb.append(name != null ? name : ""); + formatTimeMs(sb, totalTimeMillis); + if (name != null) sb.append(name); sb.append(' '); sb.append('('); sb.append(count); @@ -916,7 +912,7 @@ public abstract class BatteryStats implements Parcelable { } @SuppressWarnings("unused") - private final void dumpLocked(Printer pw, String prefix, int which) { + private final void dumpLocked(PrintWriter pw, String prefix, int which) { final long rawUptime = SystemClock.uptimeMillis() * 1000; final long rawRealtime = SystemClock.elapsedRealtime() * 1000; final long batteryUptime = getBatteryUptime(rawUptime); @@ -932,33 +928,41 @@ public abstract class BatteryStats implements Parcelable { SparseArray<? extends Uid> uidStats = getUidStats(); final int NU = uidStats.size(); - pw.println(prefix - + " Time on battery: " - + formatTimeMs(whichBatteryRealtime / 1000) + "(" - + formatRatioLocked(whichBatteryRealtime, totalRealtime) - + ") realtime, " - + formatTimeMs(whichBatteryUptime / 1000) - + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime) - + ") uptime"); - pw.println(prefix - + " Total run time: " - + formatTimeMs(totalRealtime / 1000) - + "realtime, " - + formatTimeMs(totalUptime / 1000) - + "uptime, "); + sb.setLength(0); + sb.append(prefix); + sb.append(" Time on battery: "); + formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("("); + sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime)); + sb.append(") realtime, "); + formatTimeMs(sb, whichBatteryUptime / 1000); + sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime)); + sb.append(") uptime"); + pw.println(sb.toString()); + sb.setLength(0); + sb.append(prefix); + sb.append(" Total run time: "); + formatTimeMs(sb, totalRealtime / 1000); + sb.append("realtime, "); + formatTimeMs(sb, totalUptime / 1000); + sb.append("uptime, "); + pw.println(sb.toString()); final long screenOnTime = getScreenOnTime(batteryRealtime, which); final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which); final long wifiOnTime = getWifiOnTime(batteryRealtime, which); final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); - pw.println(prefix - + " Screen on: " + formatTimeMs(screenOnTime / 1000) - + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime) - + "), Input events: " + getInputEventCount(which) - + ", Active phone call: " + formatTimeMs(phoneOnTime / 1000) - + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")"); sb.setLength(0); + sb.append(prefix); + sb.append(" Screen on: "); formatTimeMs(sb, screenOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime)); + sb.append("), Input events: "); sb.append(getInputEventCount(which)); + sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime)); + sb.append(")"); + pw.println(sb.toString()); + sb.setLength(0); + sb.append(prefix); sb.append(" Screen brightnesses: "); boolean didOne = false; for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { @@ -970,7 +974,7 @@ public abstract class BatteryStats implements Parcelable { didOne = true; sb.append(SCREEN_BRIGHTNESS_NAMES[i]); sb.append(" "); - sb.append(formatTimeMs(time/1000)); + formatTimeMs(sb, time/1000); sb.append("("); sb.append(formatRatioLocked(time, screenOnTime)); sb.append(")"); @@ -1030,16 +1034,19 @@ public abstract class BatteryStats implements Parcelable { } } - pw.println(prefix - + " Total received: " + formatBytesLocked(rxTotal) - + ", Total sent: " + formatBytesLocked(txTotal)); - pw.println(prefix - + " Total full wakelock time: " + formatTimeMs( - (fullWakeLockTimeTotalMicros + 500) / 1000) - + ", Total partial waklock time: " + formatTimeMs( - (partialWakeLockTimeTotalMicros + 500) / 1000)); + pw.print(prefix); + pw.print(" Total received: "); pw.print(formatBytesLocked(rxTotal)); + pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal)); + sb.setLength(0); + sb.append(prefix); + sb.append(" Total full wakelock time: "); formatTimeMs(sb, + (fullWakeLockTimeTotalMicros + 500) / 1000); + sb.append(", Total partial waklock time: "); formatTimeMs(sb, + (partialWakeLockTimeTotalMicros + 500) / 1000); + pw.println(sb.toString()); sb.setLength(0); + sb.append(prefix); sb.append(" Signal levels: "); didOne = false; for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { @@ -1051,7 +1058,7 @@ public abstract class BatteryStats implements Parcelable { didOne = true; sb.append(SIGNAL_STRENGTH_NAMES[i]); sb.append(" "); - sb.append(formatTimeMs(time/1000)); + formatTimeMs(sb, time/1000); sb.append("("); sb.append(formatRatioLocked(time, whichBatteryRealtime)); sb.append(") "); @@ -1062,6 +1069,7 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); sb.setLength(0); + sb.append(prefix); sb.append(" Radio types: "); didOne = false; for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { @@ -1073,7 +1081,7 @@ public abstract class BatteryStats implements Parcelable { didOne = true; sb.append(DATA_CONNECTION_NAMES[i]); sb.append(" "); - sb.append(formatTimeMs(time/1000)); + formatTimeMs(sb, time/1000); sb.append("("); sb.append(formatRatioLocked(time, whichBatteryRealtime)); sb.append(") "); @@ -1083,29 +1091,32 @@ public abstract class BatteryStats implements Parcelable { if (!didOne) sb.append("No activity"); pw.println(sb.toString()); - pw.println(prefix - + " Wifi on: " + formatTimeMs(wifiOnTime / 1000) - + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime) - + "), Wifi running: " + formatTimeMs(wifiRunningTime / 1000) - + "(" + formatRatioLocked(wifiRunningTime, whichBatteryRealtime) - + "), Bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000) - + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")"); + sb.setLength(0); + sb.append(prefix); + sb.append(" Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime)); + sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000); + sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime)); + sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)); + sb.append(")"); + pw.println(sb.toString()); pw.println(" "); if (which == STATS_UNPLUGGED) { if (getIsOnBattery()) { - pw.println(prefix + " Device is currently unplugged"); - pw.println(prefix + " Discharge cycle start level: " + - getDischargeStartLevel()); - pw.println(prefix + " Discharge cycle current level: " + - getDischargeCurrentLevel()); + pw.print(prefix); pw.println(" Device is currently unplugged"); + pw.print(prefix); pw.print(" Discharge cycle start level: "); + pw.println(getDischargeStartLevel()); + pw.print(prefix); pw.print(" Discharge cycle current level: "); + pw.println(getDischargeCurrentLevel()); } else { - pw.println(prefix + " Device is currently plugged into power"); - pw.println(prefix + " Last discharge cycle start level: " + - getDischargeStartLevel()); - pw.println(prefix + " Last discharge cycle end level: " + - getDischargeCurrentLevel()); + pw.print(prefix); pw.println(" Device is currently plugged into power"); + pw.print(prefix); pw.print(" Last discharge cycle start level: "); + pw.println(getDischargeStartLevel()); + pw.print(prefix); pw.print(" Last discharge cycle end level: "); + pw.println(getDischargeCurrentLevel()); } pw.println(" "); } @@ -1124,8 +1135,9 @@ public abstract class BatteryStats implements Parcelable { long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which); if (tcpReceived != 0 || tcpSent != 0) { - pw.println(prefix + " Network: " + formatBytesLocked(tcpReceived) + " received, " - + formatBytesLocked(tcpSent) + " sent"); + pw.print(prefix); pw.print(" Network: "); + pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, "); + pw.print(formatBytesLocked(tcpSent)); pw.println(" sent"); } if (u.hasUserActivity()) { @@ -1152,18 +1164,20 @@ public abstract class BatteryStats implements Parcelable { if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0 || wifiTurnedOnTime != 0) { - pw.println(prefix + " Turned Wifi On Time: " - + formatTimeMs(wifiTurnedOnTime / 1000) - + "(" + formatRatioLocked(wifiTurnedOnTime, - whichBatteryRealtime)+ ")"); - pw.println(prefix + " Full Wifi Lock Time: " - + formatTimeMs(fullWifiLockOnTime / 1000) - + "(" + formatRatioLocked(fullWifiLockOnTime, - whichBatteryRealtime)+ ")"); - pw.println(prefix + " Scan Wifi Lock Time: " - + formatTimeMs(scanWifiLockOnTime / 1000) - + "(" + formatRatioLocked(scanWifiLockOnTime, - whichBatteryRealtime)+ ")"); + sb.setLength(0); + sb.append(prefix); sb.append(" Turned Wifi On: "); + formatTimeMs(sb, wifiTurnedOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(wifiTurnedOnTime, + whichBatteryRealtime)); sb.append(")\n"); + sb.append(prefix); sb.append(" Full Wifi Lock: "); + formatTimeMs(sb, fullWifiLockOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime, + whichBatteryRealtime)); sb.append(")\n"); + sb.append(prefix); sb.append(" Scan Wifi Lock: "); + formatTimeMs(sb, scanWifiLockOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime, + whichBatteryRealtime)); sb.append(")"); + pw.println(sb.toString()); } Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); @@ -1217,7 +1231,7 @@ public abstract class BatteryStats implements Parcelable { int count = timer.getCountLocked(which); //timer.logState(); if (totalTime != 0) { - sb.append(formatTimeMs(totalTime)); + formatTimeMs(sb, totalTime); sb.append("realtime ("); sb.append(count); sb.append(" times)"); @@ -1247,10 +1261,15 @@ public abstract class BatteryStats implements Parcelable { starts = ps.getStarts(which); if (userTime != 0 || systemTime != 0 || starts != 0) { - pw.println(prefix + " Proc " + ent.getKey() + ":"); - pw.println(prefix + " CPU: " + formatTime(userTime) + "user + " - + formatTime(systemTime) + "kernel"); - pw.println(prefix + " " + starts + " process starts"); + sb.setLength(0); + sb.append(prefix); sb.append(" Proc "); + sb.append(ent.getKey()); sb.append(":\n"); + sb.append(prefix); sb.append(" CPU: "); + formatTime(sb, userTime); sb.append("usr + "); + formatTime(sb, systemTime); sb.append("krn\n"); + sb.append(prefix); sb.append(" "); sb.append(starts); + sb.append(" proc starts"); + pw.println(sb.toString()); uidActivity = true; } } @@ -1260,12 +1279,13 @@ public abstract class BatteryStats implements Parcelable { if (packageStats.size() > 0) { for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent : packageStats.entrySet()) { - pw.println(prefix + " Apk " + ent.getKey() + ":"); + pw.print(prefix); pw.print(" Apk "); pw.print(ent.getKey()); pw.println(":"); boolean apkActivity = false; Uid.Pkg ps = ent.getValue(); int wakeups = ps.getWakeups(which); if (wakeups != 0) { - pw.println(prefix + " " + wakeups + " wakeup alarms"); + pw.print(prefix); pw.print(" "); + pw.print(wakeups); pw.println(" wakeup alarms"); apkActivity = true; } Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); @@ -1277,24 +1297,28 @@ public abstract class BatteryStats implements Parcelable { int starts = ss.getStarts(which); int launches = ss.getLaunches(which); if (startTime != 0 || starts != 0 || launches != 0) { - pw.println(prefix + " Service " + sent.getKey() + ":"); - pw.println(prefix + " Created for: " - + formatTimeMs(startTime / 1000) - + " uptime"); - pw.println(prefix + " Starts: " + starts - + ", launches: " + launches); + sb.setLength(0); + sb.append(prefix); sb.append(" Service "); + sb.append(sent.getKey()); sb.append(":\n"); + sb.append(prefix); sb.append(" Created for: "); + formatTimeMs(sb, startTime / 1000); + sb.append(" uptime\n"); + sb.append(prefix); sb.append(" Starts: "); + sb.append(starts); + sb.append(", launches: "); sb.append(launches); + pw.println(sb.toString()); apkActivity = true; } } } if (!apkActivity) { - pw.println(prefix + " (nothing executed)"); + pw.print(prefix); pw.println(" (nothing executed)"); } uidActivity = true; } } if (!uidActivity) { - pw.println(prefix + " (nothing executed)"); + pw.print(prefix); pw.println(" (nothing executed)"); } } } @@ -1305,7 +1329,7 @@ public abstract class BatteryStats implements Parcelable { * @param pw a Printer to receive the dump output. */ @SuppressWarnings("unused") - public void dumpLocked(Printer pw) { + public void dumpLocked(PrintWriter pw) { pw.println("Total Statistics (Current and Historic):"); pw.println(" System starts: " + getStartCount() + ", currently on battery: " + getIsOnBattery()); diff --git a/core/java/android/provider/Applications.java b/core/java/android/provider/Applications.java new file mode 100644 index 0000000..0b0ce58 --- /dev/null +++ b/core/java/android/provider/Applications.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2009 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 android.provider; + +import android.app.SearchManager; +import android.net.Uri; +import android.widget.SimpleCursorAdapter; + +/** + * <p>The Applications provider gives information about installed applications.</p> + * + * <p>This provider provides the following columns: + * + * <table border="2" width="85%" align="center" frame="hsides" rules="rows"> + * + * <thead> + * <tr><th>Column Name</th> <th>Description</th> </tr> + * </thead> + * + * <tbody> + * <tr><th>{@link SearchManager#SUGGEST_COLUMN_TEXT_1}</th> + * <td>The application name.</td> + * </tr> + * + * <tr><th>{@link SearchManager#SUGGEST_COLUMN_INTENT_COMPONENT}</th> + * <td>The component to be used when forming the intent.</td> + * </tr> + * + * <tr><th>{@link SearchManager#SUGGEST_COLUMN_ICON_1}</th> + * <td>The application's icon resource id, prepended by its package name and + * separated by a colon, e.g., "com.android.alarmclock:2130837524". The + * package name is required for an activity interpreting this value to + * be able to correctly access the icon drawable, for example, in an override of + * {@link SimpleCursorAdapter#setViewImage(android.widget.ImageView, String)}.</td> + * </tr> + * + * <tr><th>{@link SearchManager#SUGGEST_COLUMN_ICON_2}</th> + * <td><i>Unused - column provided to conform to the {@link SearchManager} stipulation + * that all providers provide either both or neither of + * {@link SearchManager#SUGGEST_COLUMN_ICON_1} and + * {@link SearchManager#SUGGEST_COLUMN_ICON_2}.</td> + * </tr> + * + * @hide pending API council approval - should be unhidden at the same time as + * {@link SearchManager#SUGGEST_COLUMN_INTENT_COMPONENT} + */ +public class Applications { + private static final String TAG = "Applications"; + + /** + * The content authority for this provider. + * + * @hide + */ + public static final String AUTHORITY = "applications"; + + /** + * The content:// style URL for this provider + * + * @hide + */ + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); + + /** + * no public constructor since this is a utility class + */ + private Applications() {} +} diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index fe15553..eaace6b 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -22,8 +22,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager.NameNotFoundException; import android.os.Handler; -import android.util.Config; /** * This is a simplified version of the Search Manager service. It no longer handles @@ -36,7 +36,6 @@ public class SearchManagerService extends ISearchManager.Stub // general debugging support private static final String TAG = "SearchManagerService"; private static final boolean DEBUG = false; - private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; // configuration choices private static final boolean IMMEDIATE_SEARCHABLES_UPDATE = true; @@ -45,9 +44,10 @@ public class SearchManagerService extends ISearchManager.Stub private final Context mContext; private final Handler mHandler; private boolean mSearchablesDirty; + private Searchables mSearchables; /** - * Initialize the Search Manager service in the provided system context. + * Initializes the Search Manager service in the provided system context. * Only one instance of this object should be created! * * @param context to use for accessing DB, window manager, etc. @@ -55,6 +55,8 @@ public class SearchManagerService extends ISearchManager.Stub public SearchManagerService(Context context) { mContext = context; mHandler = new Handler(); + mSearchablesDirty = true; + mSearchables = new Searchables(context); // Setup the infrastructure for updating and maintaining the list // of searchable activities. @@ -64,7 +66,6 @@ public class SearchManagerService extends ISearchManager.Stub filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addDataScheme("package"); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); - mSearchablesDirty = true; // After startup settles down, preload the searchables list, // which will reduce the delay when the search UI is invoked. @@ -109,34 +110,41 @@ public class SearchManagerService extends ISearchManager.Stub }; /** - * Update the list of searchables, either at startup or in response to + * Updates the list of searchables, either at startup or in response to * a package add/remove broadcast message. */ private void updateSearchables() { - SearchableInfo.buildSearchableList(mContext); + mSearchables.buildSearchableList(); mSearchablesDirty = false; - // TODO This is a hack. This shouldn't be hardcoded here, it's probably - // a policy. -// ComponentName defaultSearch = new ComponentName( -// "com.android.contacts", -// "com.android.contacts.ContactsListActivity" ); - ComponentName defaultSearch = new ComponentName( - "com.android.googlesearch", - "com.android.googlesearch.GoogleSearch" ); - SearchableInfo.setDefaultSearchable(mContext, defaultSearch); + // TODO SearchableInfo should be the source of truth about whether a searchable exists. + // As it stands, if the package exists but is misconfigured in some way, then this + // would fail, and needs to be fixed. + ComponentName defaultSearch = new ComponentName( + "com.android.globalsearch", + "com.android.globalsearch.GlobalSearch"); + + try { + mContext.getPackageManager().getActivityInfo(defaultSearch, 0); + } catch (NameNotFoundException e) { + defaultSearch = new ComponentName( + "com.android.googlesearch", + "com.android.googlesearch.GoogleSearch"); + } + + mSearchables.setDefaultSearchable(defaultSearch); } /** - * Return the searchableinfo for a given activity + * Returns the SearchableInfo for a given activity * * @param launchActivity The activity from which we're launching this search. - * @return Returns a SearchableInfo record describing the parameters of the search, - * or null if no searchable metadata was available. * @param globalSearch If false, this will only launch the search that has been specifically * defined by the application (which is usually defined as a local search). If no default * search is defined in the current application or activity, no search will be launched. * If true, this will always launch a platform-global (e.g. web-based) search instead. + * @return Returns a SearchableInfo record describing the parameters of the search, + * or null if no searchable metadata was available. */ public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) { // final check. however we should try to avoid this, because @@ -146,11 +154,12 @@ public class SearchManagerService extends ISearchManager.Stub } SearchableInfo si = null; if (globalSearch) { - si = SearchableInfo.getDefaultSearchable(); + si = mSearchables.getDefaultSearchable(); } else { - si = SearchableInfo.getSearchableInfo(mContext, launchActivity); + si = mSearchables.getSearchableInfo(launchActivity); } return si; } + } diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java index 0c04839..22abd1b 100644 --- a/core/java/android/server/search/SearchableInfo.java +++ b/core/java/android/server/search/SearchableInfo.java @@ -21,14 +21,11 @@ import org.xmlpull.v1.XmlPullParserException; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; -import android.content.pm.ResolveInfo; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.text.InputType; @@ -38,9 +35,6 @@ import android.util.Xml; import android.view.inputmethod.EditorInfo; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; public final class SearchableInfo implements Parcelable { @@ -50,19 +44,12 @@ public final class SearchableInfo implements Parcelable { // set this flag to 1 to prevent any apps from providing suggestions final static int DBG_INHIBIT_SUGGESTIONS = 0; - // static strings used for XML lookups, etc. + // static strings used for XML lookups. // TODO how should these be documented for the developer, in a more structured way than // the current long wordy javadoc in SearchManager.java ? - private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable"; private static final String MD_LABEL_SEARCHABLE = "android.app.searchable"; - private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*"; private static final String MD_XML_ELEMENT_SEARCHABLE = "searchable"; private static final String MD_XML_ELEMENT_SEARCHABLE_ACTION_KEY = "actionkey"; - - // class maintenance and general shared data - private static HashMap<ComponentName, SearchableInfo> sSearchablesMap = null; - private static ArrayList<SearchableInfo> sSearchablesList = null; - private static SearchableInfo sDefaultSearchable = null; // true member variables - what we know about the searchability // TO-DO replace public with getters @@ -86,7 +73,6 @@ public final class SearchableInfo implements Parcelable { private String mSuggestIntentData = null; private ActionKeyInfo mActionKeyList = null; private String mSuggestProviderPackage = null; - private Context mCacheActivityContext = null; // use during setup only - don't hold memory! // Flag values for Searchable_voiceSearchMode private static int VOICE_SEARCH_SHOW_BUTTON = 1; @@ -97,37 +83,7 @@ public final class SearchableInfo implements Parcelable { private int mVoicePromptTextId; // voicePromptText private int mVoiceLanguageId; // voiceLanguage private int mVoiceMaxResults; // voiceMaxResults - - /** - * Set the default searchable activity (when none is specified). - */ - public static void setDefaultSearchable(Context context, - ComponentName activity) { - synchronized (SearchableInfo.class) { - SearchableInfo si = null; - if (activity != null) { - si = getSearchableInfo(context, activity); - if (si != null) { - // move to front of list - sSearchablesList.remove(si); - sSearchablesList.add(0, si); - } - } - sDefaultSearchable = si; - } - } - - /** - * Provides the system-default search activity, which you can use - * whenever getSearchableInfo() returns null; - * - * @return Returns the system-default search activity, null if never defined - */ - public static SearchableInfo getDefaultSearchable() { - synchronized (SearchableInfo.class) { - return sDefaultSearchable; - } - } + /** * Retrieve the authority for obtaining search suggestions. @@ -193,9 +149,16 @@ public final class SearchableInfo implements Parcelable { * @return Returns a context related to the searchable activity */ public Context getActivityContext(Context context) { + return createActivityContext(context, mSearchActivity); + } + + /** + * Creates a context for another activity. + */ + private static Context createActivityContext(Context context, ComponentName activity) { Context theirContext = null; try { - theirContext = context.createPackageContext(mSearchActivity.getPackageName(), 0); + theirContext = context.createPackageContext(activity.getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { // unexpected, but we deal with this by null-checking theirContext } catch (java.lang.SecurityException e) { @@ -234,242 +197,68 @@ public final class SearchableInfo implements Parcelable { } /** - * Factory. Look up, or construct, based on the activity. - * - * The activities fall into three cases, based on meta-data found in - * the manifest entry: - * <ol> - * <li>The activity itself implements search. This is indicated by the - * presence of a "android.app.searchable" meta-data attribute. - * The value is a reference to an XML file containing search information.</li> - * <li>A related activity implements search. This is indicated by the - * presence of a "android.app.default_searchable" meta-data attribute. - * The value is a string naming the activity implementing search. In this - * case the factory will "redirect" and return the searchable data.</li> - * <li>No searchability data is provided. We return null here and other - * code will insert the "default" (e.g. contacts) search. - * - * TODO: cache the result in the map, and check the map first. - * TODO: it might make sense to implement the searchable reference as - * an application meta-data entry. This way we don't have to pepper each - * and every activity. - * TODO: can we skip the constructor step if it's a non-searchable? - * TODO: does it make sense to plug the default into a slot here for - * automatic return? Probably not, but it's one way to do it. - * - * @param activity The name of the current activity, or null if the - * activity does not define any explicit searchable metadata. - */ - public static SearchableInfo getSearchableInfo(Context context, - ComponentName activity) { - // Step 1. Is the result already hashed? (case 1) - SearchableInfo result; - synchronized (SearchableInfo.class) { - result = sSearchablesMap.get(activity); - if (result != null) return result; - } - - // Step 2. See if the current activity references a searchable. - // Note: Conceptually, this could be a while(true) loop, but there's - // no point in implementing reference chaining here and risking a loop. - // References must point directly to searchable activities. - - ActivityInfo ai = null; - XmlPullParser xml = null; - try { - ai = context.getPackageManager(). - getActivityInfo(activity, PackageManager.GET_META_DATA ); - String refActivityName = null; - - // First look for activity-specific reference - Bundle md = ai.metaData; - if (md != null) { - refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); - } - // If not found, try for app-wide reference - if (refActivityName == null) { - md = ai.applicationInfo.metaData; - if (md != null) { - refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); - } - } - - // Irrespective of source, if a reference was found, follow it. - if (refActivityName != null) - { - // An app or activity can declare that we should simply launch - // "system default search" if search is invoked. - if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) { - return getDefaultSearchable(); - } - String pkg = activity.getPackageName(); - ComponentName referredActivity; - if (refActivityName.charAt(0) == '.') { - referredActivity = new ComponentName(pkg, pkg + refActivityName); - } else { - referredActivity = new ComponentName(pkg, refActivityName); - } - - // Now try the referred activity, and if found, cache - // it against the original name so we can skip the check - synchronized (SearchableInfo.class) { - result = sSearchablesMap.get(referredActivity); - if (result != null) { - sSearchablesMap.put(activity, result); - return result; - } - } - } - } catch (PackageManager.NameNotFoundException e) { - // case 3: no metadata - } - - // Step 3. None found. Return null. - return null; - - } - - /** - * Super-factory. Builds an entire list (suitable for display) of - * activities that are searchable, by iterating the entire set of - * ACTION_SEARCH intents. - * - * Also clears the hash of all activities -> searches which will - * refill as the user clicks "search". - * - * This should only be done at startup and again if we know that the - * list has changed. - * - * TODO: every activity that provides a ACTION_SEARCH intent should - * also provide searchability meta-data. There are a bunch of checks here - * that, if data is not found, silently skip to the next activity. This - * won't help a developer trying to figure out why their activity isn't - * showing up in the list, but an exception here is too rough. I would - * like to find a better notification mechanism. - * - * TODO: sort the list somehow? UI choice. - * - * @param context a context we can use during this work - */ - public static void buildSearchableList(Context context) { - - // create empty hash & list - HashMap<ComponentName, SearchableInfo> newSearchablesMap - = new HashMap<ComponentName, SearchableInfo>(); - ArrayList<SearchableInfo> newSearchablesList - = new ArrayList<SearchableInfo>(); - - // use intent resolver to generate list of ACTION_SEARCH receivers - final PackageManager pm = context.getPackageManager(); - List<ResolveInfo> infoList; - final Intent intent = new Intent(Intent.ACTION_SEARCH); - infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA); - - // analyze each one, generate a Searchables record, and record - if (infoList != null) { - int count = infoList.size(); - for (int ii = 0; ii < count; ii++) { - // for each component, try to find metadata - ResolveInfo info = infoList.get(ii); - ActivityInfo ai = info.activityInfo; - XmlResourceParser xml = ai.loadXmlMetaData(context.getPackageManager(), - MD_LABEL_SEARCHABLE); - if (xml == null) { - continue; - } - ComponentName cName = new ComponentName( - info.activityInfo.packageName, - info.activityInfo.name); - - SearchableInfo searchable = getActivityMetaData(context, xml, cName); - xml.close(); - - if (searchable != null) { - // no need to keep the context any longer. setup time is over. - searchable.mCacheActivityContext = null; - - newSearchablesList.add(searchable); - newSearchablesMap.put(cName, searchable); - } - } - } - - // record the final values as a coherent pair - synchronized (SearchableInfo.class) { - sSearchablesList = newSearchablesList; - sSearchablesMap = newSearchablesMap; - } - } - - /** * Constructor * * Given a ComponentName, get the searchability info * and build a local copy of it. Use the factory, not this. * - * @param context runtime context + * @param activityContext runtime context for the activity that the searchable info is about. * @param attr The attribute set we found in the XML file, contains the values that are used to * construct the object. * @param cName The component name of the searchable activity */ - private SearchableInfo(Context context, AttributeSet attr, final ComponentName cName) { + private SearchableInfo(Context activityContext, AttributeSet attr, final ComponentName cName) { // initialize as an "unsearchable" object mSearchable = false; mSearchActivity = cName; - // to access another activity's resources, I need its context. - // BE SURE to release the cache sometime after construction - it's a large object to hold - mCacheActivityContext = getActivityContext(context); - if (mCacheActivityContext != null) { - TypedArray a = mCacheActivityContext.obtainStyledAttributes(attr, - com.android.internal.R.styleable.Searchable); - mSearchMode = a.getInt(com.android.internal.R.styleable.Searchable_searchMode, 0); - mLabelId = a.getResourceId(com.android.internal.R.styleable.Searchable_label, 0); - mHintId = a.getResourceId(com.android.internal.R.styleable.Searchable_hint, 0); - mIconId = a.getResourceId(com.android.internal.R.styleable.Searchable_icon, 0); - mSearchButtonText = a.getResourceId( - com.android.internal.R.styleable.Searchable_searchButtonText, 0); - mSearchInputType = a.getInt(com.android.internal.R.styleable.Searchable_inputType, - InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_VARIATION_NORMAL); - mSearchImeOptions = a.getInt(com.android.internal.R.styleable.Searchable_imeOptions, - EditorInfo.IME_ACTION_SEARCH); + TypedArray a = activityContext.obtainStyledAttributes(attr, + com.android.internal.R.styleable.Searchable); + mSearchMode = a.getInt(com.android.internal.R.styleable.Searchable_searchMode, 0); + mLabelId = a.getResourceId(com.android.internal.R.styleable.Searchable_label, 0); + mHintId = a.getResourceId(com.android.internal.R.styleable.Searchable_hint, 0); + mIconId = a.getResourceId(com.android.internal.R.styleable.Searchable_icon, 0); + mSearchButtonText = a.getResourceId( + com.android.internal.R.styleable.Searchable_searchButtonText, 0); + mSearchInputType = a.getInt(com.android.internal.R.styleable.Searchable_inputType, + InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_NORMAL); + mSearchImeOptions = a.getInt(com.android.internal.R.styleable.Searchable_imeOptions, + EditorInfo.IME_ACTION_SEARCH); - setSearchModeFlags(); - if (DBG_INHIBIT_SUGGESTIONS == 0) { - mSuggestAuthority = a.getString( - com.android.internal.R.styleable.Searchable_searchSuggestAuthority); - mSuggestPath = a.getString( - com.android.internal.R.styleable.Searchable_searchSuggestPath); - mSuggestSelection = a.getString( - com.android.internal.R.styleable.Searchable_searchSuggestSelection); - mSuggestIntentAction = a.getString( - com.android.internal.R.styleable.Searchable_searchSuggestIntentAction); - mSuggestIntentData = a.getString( - com.android.internal.R.styleable.Searchable_searchSuggestIntentData); - } - mVoiceSearchMode = - a.getInt(com.android.internal.R.styleable.Searchable_voiceSearchMode, 0); - // TODO this didn't work - came back zero from YouTube - mVoiceLanguageModeId = - a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguageModel, 0); - mVoicePromptTextId = - a.getResourceId(com.android.internal.R.styleable.Searchable_voicePromptText, 0); - mVoiceLanguageId = - a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguage, 0); - mVoiceMaxResults = - a.getInt(com.android.internal.R.styleable.Searchable_voiceMaxResults, 0); + setSearchModeFlags(); + if (DBG_INHIBIT_SUGGESTIONS == 0) { + mSuggestAuthority = a.getString( + com.android.internal.R.styleable.Searchable_searchSuggestAuthority); + mSuggestPath = a.getString( + com.android.internal.R.styleable.Searchable_searchSuggestPath); + mSuggestSelection = a.getString( + com.android.internal.R.styleable.Searchable_searchSuggestSelection); + mSuggestIntentAction = a.getString( + com.android.internal.R.styleable.Searchable_searchSuggestIntentAction); + mSuggestIntentData = a.getString( + com.android.internal.R.styleable.Searchable_searchSuggestIntentData); + } + mVoiceSearchMode = + a.getInt(com.android.internal.R.styleable.Searchable_voiceSearchMode, 0); + // TODO this didn't work - came back zero from YouTube + mVoiceLanguageModeId = + a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguageModel, 0); + mVoicePromptTextId = + a.getResourceId(com.android.internal.R.styleable.Searchable_voicePromptText, 0); + mVoiceLanguageId = + a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguage, 0); + mVoiceMaxResults = + a.getInt(com.android.internal.R.styleable.Searchable_voiceMaxResults, 0); - a.recycle(); + a.recycle(); - // get package info for suggestions provider (if any) - if (mSuggestAuthority != null) { - ProviderInfo pi = - context.getPackageManager().resolveContentProvider(mSuggestAuthority, - 0); - if (pi != null) { - mSuggestProviderPackage = pi.packageName; - } + // get package info for suggestions provider (if any) + if (mSuggestAuthority != null) { + PackageManager pm = activityContext.getPackageManager(); + ProviderInfo pi = pm.resolveContentProvider(mSuggestAuthority, 0); + if (pi != null) { + mSuggestProviderPackage = pi.packageName; } } @@ -496,7 +285,7 @@ public final class SearchableInfo implements Parcelable { /** * Private class used to hold the "action key" configuration */ - public class ActionKeyInfo implements Parcelable { + public static class ActionKeyInfo implements Parcelable { public int mKeyCode = 0; public String mQueryActionMsg; @@ -506,14 +295,15 @@ public final class SearchableInfo implements Parcelable { /** * Create one object using attributeset as input data. - * @param context runtime context + * @param activityContext runtime context of the activity that the action key information + * is about. * @param attr The attribute set we found in the XML file, contains the values that are used to * construct the object. * @param next We'll build these up using a simple linked list (since there are usually * just zero or one). */ - public ActionKeyInfo(Context context, AttributeSet attr, ActionKeyInfo next) { - TypedArray a = mCacheActivityContext.obtainStyledAttributes(attr, + public ActionKeyInfo(Context activityContext, AttributeSet attr, ActionKeyInfo next) { + TypedArray a = activityContext.obtainStyledAttributes(attr, com.android.internal.R.styleable.SearchableActionKey); mKeyCode = a.getInt( @@ -584,6 +374,20 @@ public final class SearchableInfo implements Parcelable { return null; } + public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo) { + // for each component, try to find metadata + XmlResourceParser xml = + activityInfo.loadXmlMetaData(context.getPackageManager(), MD_LABEL_SEARCHABLE); + if (xml == null) { + return null; + } + ComponentName cName = new ComponentName(activityInfo.packageName, activityInfo.name); + + SearchableInfo searchable = getActivityMetaData(context, xml, cName); + xml.close(); + return searchable; + } + /** * Get the metadata for a given activity * @@ -598,6 +402,7 @@ public final class SearchableInfo implements Parcelable { private static SearchableInfo getActivityMetaData(Context context, XmlPullParser xml, final ComponentName cName) { SearchableInfo result = null; + Context activityContext = createActivityContext(context, cName); // in order to use the attributes mechanism, we have to walk the parser // forward through the file until it's reading the tag of interest. @@ -608,7 +413,7 @@ public final class SearchableInfo implements Parcelable { if (xml.getName().equals(MD_XML_ELEMENT_SEARCHABLE)) { AttributeSet attr = Xml.asAttributeSet(xml); if (attr != null) { - result = new SearchableInfo(context, attr, cName); + result = new SearchableInfo(activityContext, attr, cName); // if the constructor returned a bad object, exit now. if (! result.mSearchable) { return null; @@ -621,7 +426,7 @@ public final class SearchableInfo implements Parcelable { } AttributeSet attr = Xml.asAttributeSet(xml); if (attr != null) { - ActionKeyInfo keyInfo = result.new ActionKeyInfo(context, attr, + ActionKeyInfo keyInfo = new ActionKeyInfo(activityContext, attr, result.mActionKeyList); // only add to list if it is was useable if (keyInfo.mKeyCode != 0) { @@ -637,6 +442,7 @@ public final class SearchableInfo implements Parcelable { } catch (IOException e) { throw new RuntimeException(e); } + return result; } @@ -757,16 +563,6 @@ public final class SearchableInfo implements Parcelable { } /** - * Return the list of searchable activities, for use in the drop-down. - */ - public static ArrayList<SearchableInfo> getSearchablesList() { - synchronized (SearchableInfo.class) { - ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(sSearchablesList); - return result; - } - } - - /** * Support for parcelable and aidl operations. */ public static final Parcelable.Creator<SearchableInfo> CREATOR diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java new file mode 100644 index 0000000..ba75d21 --- /dev/null +++ b/core/java/android/server/search/Searchables.java @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2009 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 android.server.search; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * This class maintains the information about all searchable activities. + */ +public class Searchables { + + // static strings used for XML lookups, etc. + // TODO how should these be documented for the developer, in a more structured way than + // the current long wordy javadoc in SearchManager.java ? + private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable"; + private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*"; + + private Context mContext; + + private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null; + private ArrayList<SearchableInfo> mSearchablesList = null; + private SearchableInfo mDefaultSearchable = null; + + /** + * + * @param context Context to use for looking up activities etc. + */ + public Searchables (Context context) { + mContext = context; + } + + /** + * Look up, or construct, based on the activity. + * + * The activities fall into three cases, based on meta-data found in + * the manifest entry: + * <ol> + * <li>The activity itself implements search. This is indicated by the + * presence of a "android.app.searchable" meta-data attribute. + * The value is a reference to an XML file containing search information.</li> + * <li>A related activity implements search. This is indicated by the + * presence of a "android.app.default_searchable" meta-data attribute. + * The value is a string naming the activity implementing search. In this + * case the factory will "redirect" and return the searchable data.</li> + * <li>No searchability data is provided. We return null here and other + * code will insert the "default" (e.g. contacts) search. + * + * TODO: cache the result in the map, and check the map first. + * TODO: it might make sense to implement the searchable reference as + * an application meta-data entry. This way we don't have to pepper each + * and every activity. + * TODO: can we skip the constructor step if it's a non-searchable? + * TODO: does it make sense to plug the default into a slot here for + * automatic return? Probably not, but it's one way to do it. + * + * @param activity The name of the current activity, or null if the + * activity does not define any explicit searchable metadata. + */ + public SearchableInfo getSearchableInfo(ComponentName activity) { + // Step 1. Is the result already hashed? (case 1) + SearchableInfo result; + synchronized (this) { + result = mSearchablesMap.get(activity); + if (result != null) return result; + } + + // Step 2. See if the current activity references a searchable. + // Note: Conceptually, this could be a while(true) loop, but there's + // no point in implementing reference chaining here and risking a loop. + // References must point directly to searchable activities. + + ActivityInfo ai = null; + try { + ai = mContext.getPackageManager(). + getActivityInfo(activity, PackageManager.GET_META_DATA ); + String refActivityName = null; + + // First look for activity-specific reference + Bundle md = ai.metaData; + if (md != null) { + refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); + } + // If not found, try for app-wide reference + if (refActivityName == null) { + md = ai.applicationInfo.metaData; + if (md != null) { + refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); + } + } + + // Irrespective of source, if a reference was found, follow it. + if (refActivityName != null) + { + // An app or activity can declare that we should simply launch + // "system default search" if search is invoked. + if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) { + return getDefaultSearchable(); + } + String pkg = activity.getPackageName(); + ComponentName referredActivity; + if (refActivityName.charAt(0) == '.') { + referredActivity = new ComponentName(pkg, pkg + refActivityName); + } else { + referredActivity = new ComponentName(pkg, refActivityName); + } + + // Now try the referred activity, and if found, cache + // it against the original name so we can skip the check + synchronized (this) { + result = mSearchablesMap.get(referredActivity); + if (result != null) { + mSearchablesMap.put(activity, result); + return result; + } + } + } + } catch (PackageManager.NameNotFoundException e) { + // case 3: no metadata + } + + // Step 3. None found. Return null. + return null; + + } + + /** + * Set the default searchable activity (when none is specified). + */ + public synchronized void setDefaultSearchable(ComponentName activity) { + SearchableInfo si = null; + if (activity != null) { + si = getSearchableInfo(activity); + if (si != null) { + // move to front of list + mSearchablesList.remove(si); + mSearchablesList.add(0, si); + } + } + mDefaultSearchable = si; + } + + /** + * Provides the system-default search activity, which you can use + * whenever getSearchableInfo() returns null; + * + * @return Returns the system-default search activity, null if never defined + */ + public synchronized SearchableInfo getDefaultSearchable() { + return mDefaultSearchable; + } + + public synchronized boolean isDefaultSearchable(SearchableInfo searchable) { + return searchable == mDefaultSearchable; + } + + /** + * Builds an entire list (suitable for display) of + * activities that are searchable, by iterating the entire set of + * ACTION_SEARCH intents. + * + * Also clears the hash of all activities -> searches which will + * refill as the user clicks "search". + * + * This should only be done at startup and again if we know that the + * list has changed. + * + * TODO: every activity that provides a ACTION_SEARCH intent should + * also provide searchability meta-data. There are a bunch of checks here + * that, if data is not found, silently skip to the next activity. This + * won't help a developer trying to figure out why their activity isn't + * showing up in the list, but an exception here is too rough. I would + * like to find a better notification mechanism. + * + * TODO: sort the list somehow? UI choice. + */ + public void buildSearchableList() { + + // create empty hash & list + HashMap<ComponentName, SearchableInfo> newSearchablesMap + = new HashMap<ComponentName, SearchableInfo>(); + ArrayList<SearchableInfo> newSearchablesList + = new ArrayList<SearchableInfo>(); + + // use intent resolver to generate list of ACTION_SEARCH receivers + final PackageManager pm = mContext.getPackageManager(); + List<ResolveInfo> infoList; + final Intent intent = new Intent(Intent.ACTION_SEARCH); + infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA); + + // analyze each one, generate a Searchables record, and record + if (infoList != null) { + int count = infoList.size(); + for (int ii = 0; ii < count; ii++) { + // for each component, try to find metadata + ResolveInfo info = infoList.get(ii); + ActivityInfo ai = info.activityInfo; + SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai); + if (searchable != null) { + newSearchablesList.add(searchable); + newSearchablesMap.put(searchable.mSearchActivity, searchable); + } + } + } + + // record the final values as a coherent pair + synchronized (this) { + mSearchablesList = newSearchablesList; + mSearchablesMap = newSearchablesMap; + } + } + + /** + * Returns the list of searchable activities. + */ + public synchronized ArrayList<SearchableInfo> getSearchablesList() { + ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList); + return result; + } +} diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java index f9e85bf..cf210c8 100644 --- a/core/java/android/view/animation/Transformation.java +++ b/core/java/android/view/animation/Transformation.java @@ -18,6 +18,8 @@ package android.view.animation; import android.graphics.Matrix; +import java.io.PrintWriter; + /** * Defines the transformation to be applied at * one point in time of an Animation. @@ -134,14 +136,38 @@ public class Transformation { @Override public String toString() { - return "Transformation{alpha=" + mAlpha + " matrix=" - + mMatrix.toShortString() + "}"; + StringBuilder sb = new StringBuilder(64); + sb.append("Transformation"); + toShortString(sb); + return sb.toString(); } /** * Return a string representation of the transformation in a compact form. */ public String toShortString() { - return "{alpha=" + mAlpha + " matrix=" + mMatrix.toShortString() + "}"; + StringBuilder sb = new StringBuilder(64); + toShortString(sb); + return sb.toString(); + } + + /** + * @hide + */ + public void toShortString(StringBuilder sb) { + sb.append("{alpha="); sb.append(mAlpha); + sb.append(" matrix="); mMatrix.toShortString(sb); + sb.append('}'); + } + + /** + * Print short string, to optimize dumping. + * @hide + */ + public void printShortString(PrintWriter pw) { + pw.print("{alpha="); pw.print(mAlpha); + pw.print(" matrix="); + mMatrix.printShortString(pw); + pw.print('}'); } } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 772ad89..b408f27 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -983,18 +983,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mSelectorRect.setEmpty(); invalidate(); } - - /** - * The list is empty and we need to change the layout, so *really* clear everything out. - * @hide - for AutoCompleteTextView & SearchDialog only - */ - /* package */ void resetListAndClearViews() { - rememberSyncState(); - removeAllViewsInLayout(); - mRecycler.clear(); - mRecycler.setViewTypeCount(mAdapter.getViewTypeCount()); - requestLayout(); - } @Override protected int computeVerticalScrollExtent() { diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index dfb971e..e3186b0 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -110,6 +110,10 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe private final DropDownItemClickListener mDropDownItemClickListener = new DropDownItemClickListener(); + private boolean mDropDownAlwaysVisible = false; + + private boolean mDropDownDismissedOnCompletion = true; + private int mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN; private boolean mOpenBefore; @@ -211,6 +215,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p> * * @return the width for the drop down list + * + * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth */ public int getDropDownWidth() { return mDropDownWidth; @@ -222,6 +228,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p> * * @param width the width to use + * + * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth */ public void setDropDownWidth(int width) { mDropDownWidth = width; @@ -231,6 +239,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * <p>Returns the id for the view that the auto-complete drop down list is anchored to.</p> * * @return the view's id, or {@link View#NO_ID} if none specified + * + * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor */ public int getDropDownAnchor() { return mDropDownAnchorId; @@ -242,13 +252,173 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * loading a view which is not yet instantiated.</p> * * @param id the id to anchor the drop down list view to + * + * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor */ public void setDropDownAnchor(int id) { mDropDownAnchorId = id; mDropDownAnchorView = null; } + + /** + * <p>Gets the background of the auto-complete drop-down list.</p> + * + * @return the background drawable + * + * @attr ref android.R.styleable#PopupWindow_popupBackground + * + * @hide Pending API council approval + */ + public Drawable getDropDownBackground() { + return mPopup.getBackground(); + } + + /** + * <p>Sets the background of the auto-complete drop-down list.</p> + * + * @param d the drawable to set as the background + * + * @attr ref android.R.styleable#PopupWindow_popupBackground + * + * @hide Pending API council approval + */ + public void setDropDownBackgroundDrawable(Drawable d) { + mPopup.setBackgroundDrawable(d); + } + + /** + * <p>Sets the background of the auto-complete drop-down list.</p> + * + * @param id the id of the drawable to set as the background + * + * @attr ref android.R.styleable#PopupWindow_popupBackground + * + * @hide Pending API council approval + */ + public void setDropDownBackgroundResource(int id) { + mPopup.setBackgroundDrawable(getResources().getDrawable(id)); + } + + /** + * <p>Sets the animation style of the auto-complete drop-down list.</p> + * + * <p>If the drop-down is showing, calling this method will take effect only + * the next time the drop-down is shown.</p> + * + * @param animationStyle animation style to use when the drop-down appears + * and disappears. Set to -1 for the default animation, 0 for no + * animation, or a resource identifier for an explicit animation. + * + * @hide Pending API council approval + */ + public void setDropDownAnimationStyle(int animationStyle) { + mPopup.setAnimationStyle(animationStyle); + } /** + * <p>Returns the animation style that is used when the drop-down list appears and disappears + * </p> + * + * @return the animation style that is used when the drop-down list appears and disappears + * + * @hide Pending API council approval + */ + public int getDropDownAnimationStyle() { + return mPopup.getAnimationStyle(); + } + + /** + * <p>Sets the vertical offset used for the auto-complete drop-down list.</p> + * + * @param offset the vertical offset + * + * @hide Pending API council approval + */ + public void setDropDownVerticalOffset(int offset) { + mDropDownVerticalOffset = offset; + } + + /** + * <p>Gets the vertical offset used for the auto-complete drop-down list.</p> + * + * @return the vertical offset + * + * @hide Pending API council approval + */ + public int getDropDownVerticalOffset() { + return mDropDownVerticalOffset; + } + + /** + * <p>Sets the horizontal offset used for the auto-complete drop-down list.</p> + * + * @param offset the horizontal offset + * + * @hide Pending API council approval + */ + public void setDropDownHorizontalOffset(int offset) { + mDropDownHorizontalOffset = offset; + } + + /** + * <p>Gets the horizontal offset used for the auto-complete drop-down list.</p> + * + * @return the horizontal offset + * + * @hide Pending API council approval + */ + public int getDropDownHorizontalOffset() { + return mDropDownHorizontalOffset; + } + + /** + * @return Whether the drop-down is visible as long as there is {@link #enoughToFilter()} + * + * @hide Pending API council approval + */ + public boolean isDropDownAlwaysVisible() { + return mDropDownAlwaysVisible; + } + + /** + * Sets whether the drop-down should remain visible as long as there is there is + * {@link #enoughToFilter()}. This is useful if an unknown number of results are expected + * to show up in the adapter sometime in the future. + * + * The drop-down will occupy the entire screen below {@link #getDropDownAnchor} regardless + * of the size or content of the list. {@link #getDropDownBackground()} will fill any space + * that is not used by the list. + * + * @param dropDownAlwaysVisible Whether to keep the drop-down visible. + * + * @hide Pending API council approval + */ + public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) { + mDropDownAlwaysVisible = dropDownAlwaysVisible; + } + + /** + * Checks whether the drop-down is dismissed when a suggestion is clicked. + * + * @hide Pending API council approval + */ + public boolean isDropDownDismissedOnCompletion() { + return mDropDownDismissedOnCompletion; + } + + /** + * Sets whether the drop-down is dismissed when a suggestion is clicked. This is + * true by default. + * + * @param dropDownDismissedOnCompletion Whether to dismiss the drop-down. + * + * @hide Pending API council approval + */ + public void setDropDownDismissedOnCompletion(boolean dropDownDismissedOnCompletion) { + mDropDownDismissedOnCompletion = dropDownDismissedOnCompletion; + } + + /** * <p>Returns the number of characters the user must type before the drop * down list is shown.</p> * @@ -628,16 +798,6 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } return ListView.INVALID_POSITION; } - - /** - * We're changing the adapter and its views so really, really clear everything out - * @hide - for SearchDialog only - */ - public void resetListAndClearViews() { - if (mDropDownList != null) { - mDropDownList.resetListAndClearViews(); - } - } /** * <p>Starts filtering the content of the drop down list. The filtering @@ -709,7 +869,9 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } } - dismissDropDown(); + if (mDropDownDismissedOnCompletion) { + dismissDropDown(); + } } /** @@ -721,6 +883,42 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } /** + * Like {@link #setText(CharSequence)}, except that it can disable filtering. + * + * @param filter If <code>false</code>, no filtering will be performed + * as a result of this call. + * + * @hide Pending API council approval. + */ + public void setText(CharSequence text, boolean filter) { + if (filter) { + setText(text); + } else { + mBlockCompletion = true; + setText(text); + mBlockCompletion = false; + } + } + + /** + * Like {@link #setTextKeepState(CharSequence)}, except that it can disable filtering. + * + * @param filter If <code>false</code>, no filtering will be performed + * as a result of this call. + * + * @hide Pending API council approval. + */ + public void setTextKeepState(CharSequence text, boolean filter) { + if (filter) { + setTextKeepState(text); + } else { + mBlockCompletion = true; + setTextKeepState(text); + mBlockCompletion = false; + } + } + + /** * <p>Performs the text completion by replacing the current text by the * selected item. Subclasses should override this method to avoid replacing * the whole content of the edit box.</p> @@ -734,6 +932,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe Selection.setSelection(spannable, spannable.length()); } + /** {@inheritDoc} */ public void onFilterComplete(int count) { if (mAttachCount <= 0) return; @@ -744,7 +943,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * to filter. */ - if (count > 0 && enoughToFilter()) { + if ((count > 0 || mDropDownAlwaysVisible) && enoughToFilter()) { if (hasFocus() && hasWindowFocus()) { showDropDown(); } @@ -809,22 +1008,6 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } /** - * Set the horizontal offset with respect to {@link #setDropDownAnchor(int)} - * @hide pending API council review - */ - public void setDropDownHorizontalOffset(int horizontalOffset) { - mDropDownHorizontalOffset = horizontalOffset; - } - - /** - * Set the vertical offset with respect to {@link #setDropDownAnchor(int)} - * @hide pending API council review - */ - public void setDropDownVerticalOffset(int verticalOffset) { - mDropDownVerticalOffset = verticalOffset; - } - - /** * <p>Used for lazy instantiation of the anchor view from the id we have. If the value of * the id is NO_ID or we can't find a view for the given id, we return this TextView as * the default anchoring point.</p> @@ -856,10 +1039,9 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mDropDownVerticalOffset, widthSpec, height); } else { if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) { - mPopup.setWindowLayoutMode(ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT); + mPopup.setWindowLayoutMode(ViewGroup.LayoutParams.FILL_PARENT, 0); } else { - mPopup.setWindowLayoutMode(0, ViewGroup.LayoutParams.WRAP_CONTENT); + mPopup.setWindowLayoutMode(0, 0); if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { mPopup.setWidth(getDropDownAnchorView().getWidth()); } else { @@ -966,8 +1148,10 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe final int maxHeight = mPopup.getMaxAvailableHeight(this, mDropDownVerticalOffset); //otherHeights += dropDownView.getPaddingTop() + dropDownView.getPaddingBottom(); - return mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED, + final int measuredHeight = mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED, 0, ListView.NO_POSITION, maxHeight - otherHeights, 2) + otherHeights; + + return mDropDownAlwaysVisible ? maxHeight : measuredHeight; } private View getHintView(Context context) { diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 58a9be85..77649f0 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -25,6 +25,7 @@ import android.os.Process; import android.os.SystemClock; import android.telephony.TelephonyManager; import android.util.Log; +import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.SparseArray; @@ -32,6 +33,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -3096,32 +3098,33 @@ public final class BatteryStatsImpl extends BatteryStats { } }; - public void dumpLocked(Printer pw) { + public void dumpLocked(PrintWriter pw) { if (DEBUG) { - pw.println("*** Screen timer:"); - mScreenOnTimer.logState(pw, " "); + Printer pr = new PrintWriterPrinter(pw); + pr.println("*** Screen timer:"); + mScreenOnTimer.logState(pr, " "); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - pw.println("*** Screen brightness #" + i + ":"); - mScreenBrightnessTimer[i].logState(pw, " "); + pr.println("*** Screen brightness #" + i + ":"); + mScreenBrightnessTimer[i].logState(pr, " "); } - pw.println("*** Input event counter:"); - mInputEventCounter.logState(pw, " "); - pw.println("*** Phone timer:"); - mPhoneOnTimer.logState(pw, " "); + pr.println("*** Input event counter:"); + mInputEventCounter.logState(pr, " "); + pr.println("*** Phone timer:"); + mPhoneOnTimer.logState(pr, " "); for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { - pw.println("*** Signal strength #" + i + ":"); - mPhoneSignalStrengthsTimer[i].logState(pw, " "); + pr.println("*** Signal strength #" + i + ":"); + mPhoneSignalStrengthsTimer[i].logState(pr, " "); } for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { - pw.println("*** Data connection type #" + i + ":"); - mPhoneDataConnectionsTimer[i].logState(pw, " "); - } - pw.println("*** Wifi timer:"); - mWifiOnTimer.logState(pw, " "); - pw.println("*** WifiRunning timer:"); - mWifiRunningTimer.logState(pw, " "); - pw.println("*** Bluetooth timer:"); - mBluetoothOnTimer.logState(pw, " "); + pr.println("*** Data connection type #" + i + ":"); + mPhoneDataConnectionsTimer[i].logState(pr, " "); + } + pr.println("*** Wifi timer:"); + mWifiOnTimer.logState(pr, " "); + pr.println("*** WifiRunning timer:"); + mWifiRunningTimer.logState(pr, " "); + pr.println("*** Bluetooth timer:"); + mBluetoothOnTimer.logState(pr, " "); } super.dumpLocked(pw); } diff --git a/core/java/com/android/internal/util/TypedProperties.java b/core/java/com/android/internal/util/TypedProperties.java new file mode 100644 index 0000000..48479e3 --- /dev/null +++ b/core/java/com/android/internal/util/TypedProperties.java @@ -0,0 +1,692 @@ +/* + * Copyright (C) 2009 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.internal.util; + +import java.io.IOException; +import java.io.Reader; +import java.io.StreamTokenizer; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * A {@code Map} that publishes a set of typed properties, defined by + * zero or more {@code Reader}s containing textual definitions and assignments. + */ +public class TypedProperties extends HashMap<String, Object> { + /** + * Instantiates a {@link java.io.StreamTokenizer} and sets its syntax tables + * appropriately for the {@code TypedProperties} file format. + * + * @param r The {@code Reader} that the {@code StreamTokenizer} will read from + * @return a newly-created and initialized {@code StreamTokenizer} + */ + static StreamTokenizer initTokenizer(Reader r) { + StreamTokenizer st = new StreamTokenizer(r); + + // Treat everything we don't specify as "ordinary". + st.resetSyntax(); + + /* The only non-quoted-string words we'll be reading are: + * - property names: [._$a-zA-Z0-9] + * - type names (case insensitive): [a-zA-Z] + * - number literals: [-0-9.eExXA-Za-z] ('x' for 0xNNN hex literals. "NaN", "Infinity") + * - "true" or "false" (case insensitive): [a-zA-Z] + */ + st.wordChars('0', '9'); + st.wordChars('A', 'Z'); + st.wordChars('a', 'z'); + st.wordChars('_', '_'); + st.wordChars('$', '$'); + st.wordChars('.', '.'); + st.wordChars('-', '-'); + st.wordChars('+', '+'); + + // Single-character tokens + st.ordinaryChar('='); + + // Other special characters + st.whitespaceChars(' ', ' '); + st.whitespaceChars('\t', '\t'); + + st.quoteChar('"'); + + st.commentChar('#'); + + st.eolIsSignificant(true); + + return st; + } + + + /** + * An unchecked exception that is thrown when encountering a syntax + * or semantic error in the input. + */ + public static class ParseException extends IllegalArgumentException { + ParseException(StreamTokenizer state, String expected) { + super("expected " + expected + ", saw " + state.toString()); + } + } + + // A sentinel instance used to indicate a null string. + static final String NULL_STRING = new String("<TypedProperties:NULL_STRING>"); + + // Constants used to represent the supported types. + static final int TYPE_UNSET = 'x'; + static final int TYPE_BOOLEAN = 'Z'; + static final int TYPE_BYTE = 'I' | 1 << 8; + // TYPE_CHAR: character literal syntax not supported; use short. + static final int TYPE_SHORT = 'I' | 2 << 8; + static final int TYPE_INT = 'I' | 4 << 8; + static final int TYPE_LONG = 'I' | 8 << 8; + static final int TYPE_FLOAT = 'F' | 4 << 8; + static final int TYPE_DOUBLE = 'F' | 8 << 8; + static final int TYPE_STRING = 'L' | 's' << 8; + static final int TYPE_ERROR = -1; + + /** + * Converts a case-insensitive string to an internal type constant. + * + * @param typeName the type name to convert + * @return the type constant that corresponds to {@code typeName}, + * or {@code TYPE_ERROR} if the type is unknown + */ + static int interpretType(String typeName) { + if ("unset".equalsIgnoreCase(typeName)) { + return TYPE_UNSET; + } else if ("boolean".equalsIgnoreCase(typeName)) { + return TYPE_BOOLEAN; + } else if ("byte".equalsIgnoreCase(typeName)) { + return TYPE_BYTE; + } else if ("short".equalsIgnoreCase(typeName)) { + return TYPE_SHORT; + } else if ("int".equalsIgnoreCase(typeName)) { + return TYPE_INT; + } else if ("long".equalsIgnoreCase(typeName)) { + return TYPE_LONG; + } else if ("float".equalsIgnoreCase(typeName)) { + return TYPE_FLOAT; + } else if ("double".equalsIgnoreCase(typeName)) { + return TYPE_DOUBLE; + } else if ("string".equalsIgnoreCase(typeName)) { + return TYPE_STRING; + } + return TYPE_ERROR; + } + + /** + * Consumes EOL tokens. + * Returns when a non-EOL token is found. + * + * @param st The {@code StreamTokenizer} to read tokens from + * @return > 0 if an EOL token was seen, < 0 if EOF was seen, + * 0 if no tokens were consumed + */ + static int eatEols(StreamTokenizer st) throws IOException { + int token; + boolean eolSeen = false; + do { + token = st.nextToken(); + if (token == StreamTokenizer.TT_EOF) { + return -1; + } else if (token == StreamTokenizer.TT_EOL) { + eolSeen = true; + } + } while (token == StreamTokenizer.TT_EOL); + st.pushBack(); + return eolSeen ? 1 : 0; + } + + /** + * Parses the data in the reader. + * + * @param r The {@code Reader} containing input data to parse + * @param map The {@code Map} to insert parameter values into + * @throws ParseException if the input data is malformed + * @throws IOException if there is a problem reading from the {@code Reader} + */ + static void parse(Reader r, Map<String, Object> map) throws ParseException, IOException { + final StreamTokenizer st = initTokenizer(r); + + /* A property name must be a valid fully-qualified class + package name. + * We don't support Unicode, though. + */ + final String identifierPattern = "[a-zA-Z_$][0-9a-zA-Z_$]*"; + final Pattern propertyNamePattern = + Pattern.compile("(" + identifierPattern + "\\.)*" + identifierPattern); + + + boolean eolNeeded = false; + while (true) { + int token; + + // Eat one or more EOL, or quit on EOF. + int eolStatus = eatEols(st); + if (eolStatus < 0) { + // EOF occurred. + break; + } else if (eolNeeded && eolStatus == 0) { + throw new ParseException(st, "end of line or end of file"); + } + + // Read the property name. + token = st.nextToken(); + if (token != StreamTokenizer.TT_WORD) { + throw new ParseException(st, "property name"); + } + final String propertyName = st.sval; + if (!propertyNamePattern.matcher(propertyName).matches()) { + throw new ParseException(st, "valid property name"); + } + st.sval = null; + + // Read the type. + token = st.nextToken(); + if (token != StreamTokenizer.TT_WORD) { + throw new ParseException(st, "type name"); + } + final int type = interpretType(st.sval); + if (type == TYPE_ERROR) { + throw new ParseException(st, "valid type name"); + } + st.sval = null; + + if (type == TYPE_UNSET) { + map.remove(propertyName); + } else { + // Expect '='. + token = st.nextToken(); + if (token != '=') { + throw new ParseException(st, "'='"); + } + + // Read a value of the appropriate type, and insert into the map. + final Object value = parseValue(st, type); + final Object oldValue = map.remove(propertyName); + if (oldValue != null) { + // TODO: catch the case where a string is set to null and then + // the same property is defined with a different type. + if (value.getClass() != oldValue.getClass()) { + throw new ParseException(st, + "(property previously declared as a different type)"); + } + } + map.put(propertyName, value); + } + + // Require that we see at least one EOL before the next token. + eolNeeded = true; + } + } + + /** + * Parses the next token in the StreamTokenizer as the specified type. + * + * @param st The token source + * @param type The type to interpret next token as + * @return a Boolean, Number subclass, or String representing the value. + * Null strings are represented by the String instance NULL_STRING + * @throws IOException if there is a problem reading from the {@code StreamTokenizer} + */ + static Object parseValue(StreamTokenizer st, final int type) throws IOException { + final int token = st.nextToken(); + + if (type == TYPE_BOOLEAN) { + if (token != StreamTokenizer.TT_WORD) { + throw new ParseException(st, "boolean constant"); + } + + if ("true".equalsIgnoreCase(st.sval)) { + return Boolean.TRUE; + } else if ("false".equalsIgnoreCase(st.sval)) { + return Boolean.FALSE; + } + + throw new ParseException(st, "boolean constant"); + } else if ((type & 0xff) == 'I') { + if (token != StreamTokenizer.TT_WORD) { + throw new ParseException(st, "integer constant"); + } + + /* Parse the string. Long.decode() handles C-style integer constants + * ("0x" -> hex, "0" -> octal). It also treats numbers with a prefix of "#" as + * hex, but our syntax intentionally does not list '#' as a word character. + */ + long value; + try { + value = Long.decode(st.sval); + } catch (NumberFormatException ex) { + throw new ParseException(st, "integer constant"); + } + + // Ensure that the type can hold this value, and return. + int width = (type >> 8) & 0xff; + switch (width) { + case 1: + if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { + throw new ParseException(st, "8-bit integer constant"); + } + return new Byte((byte)value); + case 2: + if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { + throw new ParseException(st, "16-bit integer constant"); + } + return new Short((short)value); + case 4: + if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { + throw new ParseException(st, "32-bit integer constant"); + } + return new Integer((int)value); + case 8: + if (value < Long.MIN_VALUE || value > Long.MAX_VALUE) { + throw new ParseException(st, "64-bit integer constant"); + } + return new Long(value); + default: + throw new IllegalStateException( + "Internal error; unexpected integer type width " + width); + } + } else if ((type & 0xff) == 'F') { + if (token != StreamTokenizer.TT_WORD) { + throw new ParseException(st, "float constant"); + } + + // Parse the string. + /* TODO: Maybe just parse as float or double, losing precision if necessary. + * Parsing as double and converting to float can change the value + * compared to just parsing as float. + */ + double value; + try { + /* TODO: detect if the string representation loses precision + * when being converted to a double. + */ + value = Double.parseDouble(st.sval); + } catch (NumberFormatException ex) { + throw new ParseException(st, "float constant"); + } + + // Ensure that the type can hold this value, and return. + if (((type >> 8) & 0xff) == 4) { + // This property is a float; make sure the value fits. + double absValue = Math.abs(value); + if (absValue != 0.0 && !Double.isInfinite(value) && !Double.isNaN(value)) { + if (absValue < Float.MIN_VALUE || absValue > Float.MAX_VALUE) { + throw new ParseException(st, "32-bit float constant"); + } + } + return new Float((float)value); + } else { + // This property is a double; no need to truncate. + return new Double(value); + } + } else if (type == TYPE_STRING) { + // Expect a quoted string or the word "null". + if (token == '"') { + return st.sval; + } else if (token == StreamTokenizer.TT_WORD && "null".equalsIgnoreCase(st.sval)) { + return NULL_STRING; + } + throw new ParseException(st, "double-quoted string or 'null'"); + } + + throw new IllegalStateException("Internal error; unknown type " + type); + } + + + /** + * Creates an empty TypedProperties instance. + */ + public TypedProperties() { + super(); + } + + /** + * Loads zero or more properties from the specified Reader. + * Properties that have already been loaded are preserved unless + * the new Reader overrides or unsets earlier values for the + * same properties. + * + * File syntax: + * + * <property-name> <type> = <value> + * <property-name> unset + * + * '#' is a comment character; it and anything appearing after it + * on the line is ignored. + * + * Blank lines are ignored. + * + * The only required whitespace is between the property name + * and the type. + * + * Property assignments may not be split across multiple lines. + * + * <property-name> is a valid fully-qualified class name + * (one or more valid identifiers separated by dot characters). + * + * <type> is one of {boolean, byte, short, int, long, + * float, double, string}, and is case-insensitive. + * + * <value> depends on the type: + * - boolean: one of {true, false} (case-insensitive) + * - byte, short, int, long: a valid Java integer constant + * (including non-base-10 constants like 0xabc and 074) + * whose value does not overflow the type. NOTE: these are + * interpreted as Java integer values, so they are all signed. + * - float, double: a valid Java floating-point constant. + * If the type is float, the value must fit in 32 bits. + * - string: a double-quoted string value, or the word {@code null}. + * NOTE: the contents of the string must be 7-bit clean ASCII; + * C-style octal escapes are recognized, but Unicode escapes are not. + * + * + * @param r The Reader to load properties from + * @throws IOException if an error occurs when reading the data + * @throws IllegalArgumentException if the data is malformed + */ + public void load(Reader r) throws IOException { + parse(r, this); + } + + @Override + public Object get(Object key) { + Object value = super.get(key); + if (value == NULL_STRING) { + return null; + } + return value; + } + + /* + * Getters with explicit defaults + */ + + /** + * An unchecked exception that is thrown if a {@code get<TYPE>()} method + * is used to retrieve a parameter whose type does not match the method name. + */ + public static class TypeException extends IllegalArgumentException { + TypeException(String property, Object value, String requestedType) { + super(property + " has type " + value.getClass().getName() + + ", not " + requestedType); + } + } + + /** + * Returns the value of a boolean property, or the default if the property + * has not been defined. + * + * @param property The name of the property to return + * @param def The default value to return if the property is not set + * @return the value of the property + * @throws TypeException if the property is set and is not a boolean + */ + public boolean getBoolean(String property, boolean def) { + Object value = super.get(property); + if (value == null) { + return def; + } + if (value instanceof Boolean) { + return ((Boolean)value).booleanValue(); + } + throw new TypeException(property, value, "boolean"); + } + + /** + * Returns the value of a byte property, or the default if the property + * has not been defined. + * + * @param property The name of the property to return + * @param def The default value to return if the property is not set + * @return the value of the property + * @throws TypeException if the property is set and is not a byte + */ + public byte getByte(String property, byte def) { + Object value = super.get(property); + if (value == null) { + return def; + } + if (value instanceof Byte) { + return ((Byte)value).byteValue(); + } + throw new TypeException(property, value, "byte"); + } + + /** + * Returns the value of a short property, or the default if the property + * has not been defined. + * + * @param property The name of the property to return + * @param def The default value to return if the property is not set + * @return the value of the property + * @throws TypeException if the property is set and is not a short + */ + public short getShort(String property, short def) { + Object value = super.get(property); + if (value == null) { + return def; + } + if (value instanceof Short) { + return ((Short)value).shortValue(); + } + throw new TypeException(property, value, "short"); + } + + /** + * Returns the value of an integer property, or the default if the property + * has not been defined. + * + * @param property The name of the property to return + * @param def The default value to return if the property is not set + * @return the value of the property + * @throws TypeException if the property is set and is not an integer + */ + public int getInt(String property, int def) { + Object value = super.get(property); + if (value == null) { + return def; + } + if (value instanceof Integer) { + return ((Integer)value).intValue(); + } + throw new TypeException(property, value, "int"); + } + + /** + * Returns the value of a long property, or the default if the property + * has not been defined. + * + * @param property The name of the property to return + * @param def The default value to return if the property is not set + * @return the value of the property + * @throws TypeException if the property is set and is not a long + */ + public long getLong(String property, long def) { + Object value = super.get(property); + if (value == null) { + return def; + } + if (value instanceof Long) { + return ((Long)value).longValue(); + } + throw new TypeException(property, value, "long"); + } + + /** + * Returns the value of a float property, or the default if the property + * has not been defined. + * + * @param property The name of the property to return + * @param def The default value to return if the property is not set + * @return the value of the property + * @throws TypeException if the property is set and is not a float + */ + public float getFloat(String property, float def) { + Object value = super.get(property); + if (value == null) { + return def; + } + if (value instanceof Float) { + return ((Float)value).floatValue(); + } + throw new TypeException(property, value, "float"); + } + + /** + * Returns the value of a double property, or the default if the property + * has not been defined. + * + * @param property The name of the property to return + * @param def The default value to return if the property is not set + * @return the value of the property + * @throws TypeException if the property is set and is not a double + */ + public double getDouble(String property, double def) { + Object value = super.get(property); + if (value == null) { + return def; + } + if (value instanceof Double) { + return ((Double)value).doubleValue(); + } + throw new TypeException(property, value, "double"); + } + + /** + * Returns the value of a string property, or the default if the property + * has not been defined. + * + * @param property The name of the property to return + * @param def The default value to return if the property is not set + * @return the value of the property + * @throws TypeException if the property is set and is not a string + */ + public String getString(String property, String def) { + Object value = super.get(property); + if (value == null) { + return def; + } + if (value == NULL_STRING) { + return null; + } else if (value instanceof String) { + return (String)value; + } + throw new TypeException(property, value, "string"); + } + + /* + * Getters with implicit defaults + */ + + /** + * Returns the value of a boolean property, or false + * if the property has not been defined. + * + * @param property The name of the property to return + * @return the value of the property + * @throws TypeException if the property is set and is not a boolean + */ + public boolean getBoolean(String property) { + return getBoolean(property, false); + } + + /** + * Returns the value of a byte property, or 0 + * if the property has not been defined. + * + * @param property The name of the property to return + * @return the value of the property + * @throws TypeException if the property is set and is not a byte + */ + public byte getByte(String property) { + return getByte(property, (byte)0); + } + + /** + * Returns the value of a short property, or 0 + * if the property has not been defined. + * + * @param property The name of the property to return + * @return the value of the property + * @throws TypeException if the property is set and is not a short + */ + public short getShort(String property) { + return getShort(property, (short)0); + } + + /** + * Returns the value of an integer property, or 0 + * if the property has not been defined. + * + * @param property The name of the property to return + * @return the value of the property + * @throws TypeException if the property is set and is not an integer + */ + public int getInt(String property) { + return getInt(property, 0); + } + + /** + * Returns the value of a long property, or 0 + * if the property has not been defined. + * + * @param property The name of the property to return + * @return the value of the property + * @throws TypeException if the property is set and is not a long + */ + public long getLong(String property) { + return getLong(property, 0L); + } + + /** + * Returns the value of a float property, or 0.0 + * if the property has not been defined. + * + * @param property The name of the property to return + * @return the value of the property + * @throws TypeException if the property is set and is not a float + */ + public float getFloat(String property) { + return getFloat(property, 0.0f); + } + + /** + * Returns the value of a double property, or 0.0 + * if the property has not been defined. + * + * @param property The name of the property to return + * @return the value of the property + * @throws TypeException if the property is set and is not a double + */ + public double getDouble(String property) { + return getDouble(property, 0.0); + } + + /** + * Returns the value of a String property, or "" + * if the property has not been defined. + * + * @param property The name of the property to return + * @return the value of the property + * @throws TypeException if the property is set and is not a string + */ + public String getString(String property) { + return getString(property, ""); + } +} diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp index 117ff35..bc644d2 100644 --- a/core/jni/android_opengl_GLES10.cpp +++ b/core/jni/android_opengl_GLES10.cpp @@ -3434,7 +3434,7 @@ static JNINativeMethod methods[] = { {"glGetError", "()I", (void *) android_glGetError__ }, {"glGetIntegerv", "(I[II)V", (void *) android_glGetIntegerv__I_3II }, {"glGetIntegerv", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetIntegerv__ILjava_nio_IntBuffer_2 }, -{"_glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString }, +{"glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString }, {"glHint", "(II)V", (void *) android_glHint__II }, {"glLightModelf", "(IF)V", (void *) android_glLightModelf__IF }, {"glLightModelfv", "(I[FI)V", (void *) android_glLightModelfv__I_3FI }, diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp index 2576d8a..069cec1 100644 --- a/core/jni/android_opengl_GLES11Ext.cpp +++ b/core/jni/android_opengl_GLES11Ext.cpp @@ -132,24 +132,31 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) static void android_glBlendEquationSeparateOES__II (JNIEnv *_env, jobject _this, jint modeRGB, jint modeAlpha) { - _env->ThrowNew(UOEClass, - "glBlendEquationSeparateOES"); + glBlendEquationSeparateOES( + (GLenum)modeRGB, + (GLenum)modeAlpha + ); } /* void glBlendFuncSeparateOES ( GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha ) */ static void android_glBlendFuncSeparateOES__IIII (JNIEnv *_env, jobject _this, jint srcRGB, jint dstRGB, jint srcAlpha, jint dstAlpha) { - _env->ThrowNew(UOEClass, - "glBlendFuncSeparateOES"); + glBlendFuncSeparateOES( + (GLenum)srcRGB, + (GLenum)dstRGB, + (GLenum)srcAlpha, + (GLenum)dstAlpha + ); } /* void glBlendEquationOES ( GLenum mode ) */ static void android_glBlendEquationOES__I (JNIEnv *_env, jobject _this, jint mode) { - _env->ThrowNew(UOEClass, - "glBlendEquationOES"); + glBlendEquationOES( + (GLenum)mode + ); } /* void glDrawTexsOES ( GLshort x, GLshort y, GLshort z, GLshort width, GLshort height ) */ @@ -444,456 +451,1153 @@ exit: static void android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2 (JNIEnv *_env, jobject _this, jint target, jobject image_buf) { - _env->ThrowNew(UOEClass, - "glEGLImageTargetTexture2DOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLeglImageOES image = (GLeglImageOES) 0; + + image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining); + glEGLImageTargetTexture2DOES( + (GLenum)target, + (GLeglImageOES)image + ); + if (_array) { + releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glEGLImageTargetRenderbufferStorageOES ( GLenum target, GLeglImageOES image ) */ static void android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2 (JNIEnv *_env, jobject _this, jint target, jobject image_buf) { - _env->ThrowNew(UOEClass, - "glEGLImageTargetRenderbufferStorageOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLeglImageOES image = (GLeglImageOES) 0; + + image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining); + glEGLImageTargetRenderbufferStorageOES( + (GLenum)target, + (GLeglImageOES)image + ); + if (_array) { + releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glAlphaFuncxOES ( GLenum func, GLclampx ref ) */ static void android_glAlphaFuncxOES__II (JNIEnv *_env, jobject _this, jint func, jint ref) { - _env->ThrowNew(UOEClass, - "glAlphaFuncxOES"); + glAlphaFuncxOES( + (GLenum)func, + (GLclampx)ref + ); } /* void glClearColorxOES ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha ) */ static void android_glClearColorxOES__IIII (JNIEnv *_env, jobject _this, jint red, jint green, jint blue, jint alpha) { - _env->ThrowNew(UOEClass, - "glClearColorxOES"); + glClearColorxOES( + (GLclampx)red, + (GLclampx)green, + (GLclampx)blue, + (GLclampx)alpha + ); } /* void glClearDepthxOES ( GLclampx depth ) */ static void android_glClearDepthxOES__I (JNIEnv *_env, jobject _this, jint depth) { - _env->ThrowNew(UOEClass, - "glClearDepthxOES"); + glClearDepthxOES( + (GLclampx)depth + ); } /* void glClipPlanexOES ( GLenum plane, const GLfixed *equation ) */ static void android_glClipPlanexOES__I_3II (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glClipPlanexOES"); + GLfixed *equation_base = (GLfixed *) 0; + jint _remaining; + GLfixed *equation = (GLfixed *) 0; + + if (!equation_ref) { + _env->ThrowNew(IAEClass, "equation == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(equation_ref) - offset; + equation_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(equation_ref, (jboolean *)0); + equation = equation_base + offset; + + glClipPlanexOES( + (GLenum)plane, + (GLfixed *)equation + ); + +exit: + if (equation_base) { + _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base, + JNI_ABORT); + } } /* void glClipPlanexOES ( GLenum plane, const GLfixed *equation ) */ static void android_glClipPlanexOES__ILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) { - _env->ThrowNew(UOEClass, - "glClipPlanexOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *equation = (GLfixed *) 0; + + equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining); + glClipPlanexOES( + (GLenum)plane, + (GLfixed *)equation + ); + if (_array) { + releasePointer(_env, _array, equation, JNI_FALSE); + } } /* void glColor4xOES ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha ) */ static void android_glColor4xOES__IIII (JNIEnv *_env, jobject _this, jint red, jint green, jint blue, jint alpha) { - _env->ThrowNew(UOEClass, - "glColor4xOES"); + glColor4xOES( + (GLfixed)red, + (GLfixed)green, + (GLfixed)blue, + (GLfixed)alpha + ); } /* void glDepthRangexOES ( GLclampx zNear, GLclampx zFar ) */ static void android_glDepthRangexOES__II (JNIEnv *_env, jobject _this, jint zNear, jint zFar) { - _env->ThrowNew(UOEClass, - "glDepthRangexOES"); + glDepthRangexOES( + (GLclampx)zNear, + (GLclampx)zFar + ); } /* void glFogxOES ( GLenum pname, GLfixed param ) */ static void android_glFogxOES__II (JNIEnv *_env, jobject _this, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glFogxOES"); + glFogxOES( + (GLenum)pname, + (GLfixed)param + ); } /* void glFogxvOES ( GLenum pname, const GLfixed *params ) */ static void android_glFogxvOES__I_3II (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glFogxvOES"); + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glFogxvOES( + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glFogxvOES ( GLenum pname, const GLfixed *params ) */ static void android_glFogxvOES__ILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glFogxvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glFogxvOES( + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glFrustumxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) */ static void android_glFrustumxOES__IIIIII (JNIEnv *_env, jobject _this, jint left, jint right, jint bottom, jint top, jint zNear, jint zFar) { - _env->ThrowNew(UOEClass, - "glFrustumxOES"); + glFrustumxOES( + (GLfixed)left, + (GLfixed)right, + (GLfixed)bottom, + (GLfixed)top, + (GLfixed)zNear, + (GLfixed)zFar + ); } /* void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn ) */ static void android_glGetClipPlanexOES__I_3II (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetClipPlanexOES"); + jint _exception = 0; + GLfixed *eqn_base = (GLfixed *) 0; + jint _remaining; + GLfixed *eqn = (GLfixed *) 0; + + if (!eqn_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "eqn == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(eqn_ref) - offset; + if (_remaining < 4) { + _exception = 1; + _env->ThrowNew(IAEClass, "length - offset < 4"); + goto exit; + } + eqn_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(eqn_ref, (jboolean *)0); + eqn = eqn_base + offset; + + glGetClipPlanexOES( + (GLenum)pname, + (GLfixed *)eqn + ); + +exit: + if (eqn_base) { + _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn ) */ static void android_glGetClipPlanexOES__ILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) { - _env->ThrowNew(UOEClass, - "glGetClipPlanexOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *eqn = (GLfixed *) 0; + + eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining); + if (_remaining < 4) { + _exception = 1; + _env->ThrowNew(IAEClass, "remaining() < 4"); + goto exit; + } + glGetClipPlanexOES( + (GLenum)pname, + (GLfixed *)eqn + ); + +exit: + if (_array) { + releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glGetFixedvOES ( GLenum pname, GLfixed *params ) */ static void android_glGetFixedvOES__I_3II (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetFixedvOES"); + jint _exception = 0; + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glGetFixedvOES( + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetFixedvOES ( GLenum pname, GLfixed *params ) */ static void android_glGetFixedvOES__ILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glGetFixedvOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glGetFixedvOES( + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params ) */ static void android_glGetLightxvOES__II_3II (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetLightxvOES"); + jint _exception = 0; + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glGetLightxvOES( + (GLenum)light, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params ) */ static void android_glGetLightxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glGetLightxvOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glGetLightxvOES( + (GLenum)light, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params ) */ static void android_glGetMaterialxvOES__II_3II (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetMaterialxvOES"); + jint _exception = 0; + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glGetMaterialxvOES( + (GLenum)face, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params ) */ static void android_glGetMaterialxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glGetMaterialxvOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glGetMaterialxvOES( + (GLenum)face, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params ) */ static void android_glGetTexEnvxvOES__II_3II (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetTexEnvxvOES"); + jint _exception = 0; + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glGetTexEnvxvOES( + (GLenum)env, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params ) */ static void android_glGetTexEnvxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glGetTexEnvxvOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glGetTexEnvxvOES( + (GLenum)env, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params ) */ static void android_glGetTexParameterxvOES__II_3II (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetTexParameterxvOES"); + jint _exception = 0; + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glGetTexParameterxvOES( + (GLenum)target, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params ) */ static void android_glGetTexParameterxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glGetTexParameterxvOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glGetTexParameterxvOES( + (GLenum)target, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glLightModelxOES ( GLenum pname, GLfixed param ) */ static void android_glLightModelxOES__II (JNIEnv *_env, jobject _this, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glLightModelxOES"); + glLightModelxOES( + (GLenum)pname, + (GLfixed)param + ); } /* void glLightModelxvOES ( GLenum pname, const GLfixed *params ) */ static void android_glLightModelxvOES__I_3II (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glLightModelxvOES"); + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glLightModelxvOES( + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glLightModelxvOES ( GLenum pname, const GLfixed *params ) */ static void android_glLightModelxvOES__ILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glLightModelxvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glLightModelxvOES( + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glLightxOES ( GLenum light, GLenum pname, GLfixed param ) */ static void android_glLightxOES__III (JNIEnv *_env, jobject _this, jint light, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glLightxOES"); + glLightxOES( + (GLenum)light, + (GLenum)pname, + (GLfixed)param + ); } /* void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params ) */ static void android_glLightxvOES__II_3II (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glLightxvOES"); + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glLightxvOES( + (GLenum)light, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params ) */ static void android_glLightxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glLightxvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glLightxvOES( + (GLenum)light, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glLineWidthxOES ( GLfixed width ) */ static void android_glLineWidthxOES__I (JNIEnv *_env, jobject _this, jint width) { - _env->ThrowNew(UOEClass, - "glLineWidthxOES"); + glLineWidthxOES( + (GLfixed)width + ); } /* void glLoadMatrixxOES ( const GLfixed *m ) */ static void android_glLoadMatrixxOES___3II (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glLoadMatrixxOES"); + GLfixed *m_base = (GLfixed *) 0; + jint _remaining; + GLfixed *m = (GLfixed *) 0; + + if (!m_ref) { + _env->ThrowNew(IAEClass, "m == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(m_ref) - offset; + m_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(m_ref, (jboolean *)0); + m = m_base + offset; + + glLoadMatrixxOES( + (GLfixed *)m + ); + +exit: + if (m_base) { + _env->ReleasePrimitiveArrayCritical(m_ref, m_base, + JNI_ABORT); + } } /* void glLoadMatrixxOES ( const GLfixed *m ) */ static void android_glLoadMatrixxOES__Ljava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jobject m_buf) { - _env->ThrowNew(UOEClass, - "glLoadMatrixxOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *m = (GLfixed *) 0; + + m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining); + glLoadMatrixxOES( + (GLfixed *)m + ); + if (_array) { + releasePointer(_env, _array, m, JNI_FALSE); + } } /* void glMaterialxOES ( GLenum face, GLenum pname, GLfixed param ) */ static void android_glMaterialxOES__III (JNIEnv *_env, jobject _this, jint face, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glMaterialxOES"); + glMaterialxOES( + (GLenum)face, + (GLenum)pname, + (GLfixed)param + ); } /* void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params ) */ static void android_glMaterialxvOES__II_3II (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glMaterialxvOES"); + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glMaterialxvOES( + (GLenum)face, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params ) */ static void android_glMaterialxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glMaterialxvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glMaterialxvOES( + (GLenum)face, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glMultMatrixxOES ( const GLfixed *m ) */ static void android_glMultMatrixxOES___3II (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glMultMatrixxOES"); + GLfixed *m_base = (GLfixed *) 0; + jint _remaining; + GLfixed *m = (GLfixed *) 0; + + if (!m_ref) { + _env->ThrowNew(IAEClass, "m == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(m_ref) - offset; + m_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(m_ref, (jboolean *)0); + m = m_base + offset; + + glMultMatrixxOES( + (GLfixed *)m + ); + +exit: + if (m_base) { + _env->ReleasePrimitiveArrayCritical(m_ref, m_base, + JNI_ABORT); + } } /* void glMultMatrixxOES ( const GLfixed *m ) */ static void android_glMultMatrixxOES__Ljava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jobject m_buf) { - _env->ThrowNew(UOEClass, - "glMultMatrixxOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *m = (GLfixed *) 0; + + m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining); + glMultMatrixxOES( + (GLfixed *)m + ); + if (_array) { + releasePointer(_env, _array, m, JNI_FALSE); + } } /* void glMultiTexCoord4xOES ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q ) */ static void android_glMultiTexCoord4xOES__IIIII (JNIEnv *_env, jobject _this, jint target, jint s, jint t, jint r, jint q) { - _env->ThrowNew(UOEClass, - "glMultiTexCoord4xOES"); + glMultiTexCoord4xOES( + (GLenum)target, + (GLfixed)s, + (GLfixed)t, + (GLfixed)r, + (GLfixed)q + ); } /* void glNormal3xOES ( GLfixed nx, GLfixed ny, GLfixed nz ) */ static void android_glNormal3xOES__III (JNIEnv *_env, jobject _this, jint nx, jint ny, jint nz) { - _env->ThrowNew(UOEClass, - "glNormal3xOES"); + glNormal3xOES( + (GLfixed)nx, + (GLfixed)ny, + (GLfixed)nz + ); } /* void glOrthoxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) */ static void android_glOrthoxOES__IIIIII (JNIEnv *_env, jobject _this, jint left, jint right, jint bottom, jint top, jint zNear, jint zFar) { - _env->ThrowNew(UOEClass, - "glOrthoxOES"); + glOrthoxOES( + (GLfixed)left, + (GLfixed)right, + (GLfixed)bottom, + (GLfixed)top, + (GLfixed)zNear, + (GLfixed)zFar + ); } /* void glPointParameterxOES ( GLenum pname, GLfixed param ) */ static void android_glPointParameterxOES__II (JNIEnv *_env, jobject _this, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glPointParameterxOES"); + glPointParameterxOES( + (GLenum)pname, + (GLfixed)param + ); } /* void glPointParameterxvOES ( GLenum pname, const GLfixed *params ) */ static void android_glPointParameterxvOES__I_3II (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glPointParameterxvOES"); + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glPointParameterxvOES( + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glPointParameterxvOES ( GLenum pname, const GLfixed *params ) */ static void android_glPointParameterxvOES__ILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glPointParameterxvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glPointParameterxvOES( + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glPointSizexOES ( GLfixed size ) */ static void android_glPointSizexOES__I (JNIEnv *_env, jobject _this, jint size) { - _env->ThrowNew(UOEClass, - "glPointSizexOES"); + glPointSizexOES( + (GLfixed)size + ); } /* void glPolygonOffsetxOES ( GLfixed factor, GLfixed units ) */ static void android_glPolygonOffsetxOES__II (JNIEnv *_env, jobject _this, jint factor, jint units) { - _env->ThrowNew(UOEClass, - "glPolygonOffsetxOES"); + glPolygonOffsetxOES( + (GLfixed)factor, + (GLfixed)units + ); } /* void glRotatexOES ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z ) */ static void android_glRotatexOES__IIII (JNIEnv *_env, jobject _this, jint angle, jint x, jint y, jint z) { - _env->ThrowNew(UOEClass, - "glRotatexOES"); + glRotatexOES( + (GLfixed)angle, + (GLfixed)x, + (GLfixed)y, + (GLfixed)z + ); } /* void glSampleCoveragexOES ( GLclampx value, GLboolean invert ) */ static void android_glSampleCoveragexOES__IZ (JNIEnv *_env, jobject _this, jint value, jboolean invert) { - _env->ThrowNew(UOEClass, - "glSampleCoveragexOES"); + glSampleCoveragexOES( + (GLclampx)value, + (GLboolean)invert + ); } /* void glScalexOES ( GLfixed x, GLfixed y, GLfixed z ) */ static void android_glScalexOES__III (JNIEnv *_env, jobject _this, jint x, jint y, jint z) { - _env->ThrowNew(UOEClass, - "glScalexOES"); + glScalexOES( + (GLfixed)x, + (GLfixed)y, + (GLfixed)z + ); } /* void glTexEnvxOES ( GLenum target, GLenum pname, GLfixed param ) */ static void android_glTexEnvxOES__III (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glTexEnvxOES"); + glTexEnvxOES( + (GLenum)target, + (GLenum)pname, + (GLfixed)param + ); } /* void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */ static void android_glTexEnvxvOES__II_3II (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glTexEnvxvOES"); + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glTexEnvxvOES( + (GLenum)target, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */ static void android_glTexEnvxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glTexEnvxvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glTexEnvxvOES( + (GLenum)target, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glTexParameterxOES ( GLenum target, GLenum pname, GLfixed param ) */ static void android_glTexParameterxOES__III (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glTexParameterxOES"); + glTexParameterxOES( + (GLenum)target, + (GLenum)pname, + (GLfixed)param + ); } /* void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */ static void android_glTexParameterxvOES__II_3II (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glTexParameterxvOES"); + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glTexParameterxvOES( + (GLenum)target, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */ static void android_glTexParameterxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glTexParameterxvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glTexParameterxvOES( + (GLenum)target, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glTranslatexOES ( GLfixed x, GLfixed y, GLfixed z ) */ static void android_glTranslatexOES__III (JNIEnv *_env, jobject _this, jint x, jint y, jint z) { - _env->ThrowNew(UOEClass, - "glTranslatexOES"); + glTranslatexOES( + (GLfixed)x, + (GLfixed)y, + (GLfixed)z + ); } /* GLboolean glIsRenderbufferOES ( GLuint renderbuffer ) */ @@ -1103,184 +1807,528 @@ android_glWeightPointerOES__IIILjava_nio_Buffer_2 static void android_glDepthRangefOES__FF (JNIEnv *_env, jobject _this, jfloat zNear, jfloat zFar) { - _env->ThrowNew(UOEClass, - "glDepthRangefOES"); + glDepthRangefOES( + (GLclampf)zNear, + (GLclampf)zFar + ); } /* void glFrustumfOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */ static void android_glFrustumfOES__FFFFFF (JNIEnv *_env, jobject _this, jfloat left, jfloat right, jfloat bottom, jfloat top, jfloat zNear, jfloat zFar) { - _env->ThrowNew(UOEClass, - "glFrustumfOES"); + glFrustumfOES( + (GLfloat)left, + (GLfloat)right, + (GLfloat)bottom, + (GLfloat)top, + (GLfloat)zNear, + (GLfloat)zFar + ); } /* void glOrthofOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */ static void android_glOrthofOES__FFFFFF (JNIEnv *_env, jobject _this, jfloat left, jfloat right, jfloat bottom, jfloat top, jfloat zNear, jfloat zFar) { - _env->ThrowNew(UOEClass, - "glOrthofOES"); + glOrthofOES( + (GLfloat)left, + (GLfloat)right, + (GLfloat)bottom, + (GLfloat)top, + (GLfloat)zNear, + (GLfloat)zFar + ); } /* void glClipPlanefOES ( GLenum plane, const GLfloat *equation ) */ static void android_glClipPlanefOES__I_3FI (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glClipPlanefOES"); + GLfloat *equation_base = (GLfloat *) 0; + jint _remaining; + GLfloat *equation = (GLfloat *) 0; + + if (!equation_ref) { + _env->ThrowNew(IAEClass, "equation == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(equation_ref) - offset; + equation_base = (GLfloat *) + _env->GetPrimitiveArrayCritical(equation_ref, (jboolean *)0); + equation = equation_base + offset; + + glClipPlanefOES( + (GLenum)plane, + (GLfloat *)equation + ); + +exit: + if (equation_base) { + _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base, + JNI_ABORT); + } } /* void glClipPlanefOES ( GLenum plane, const GLfloat *equation ) */ static void android_glClipPlanefOES__ILjava_nio_FloatBuffer_2 (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) { - _env->ThrowNew(UOEClass, - "glClipPlanefOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfloat *equation = (GLfloat *) 0; + + equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining); + glClipPlanefOES( + (GLenum)plane, + (GLfloat *)equation + ); + if (_array) { + releasePointer(_env, _array, equation, JNI_FALSE); + } } /* void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn ) */ static void android_glGetClipPlanefOES__I_3FI (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetClipPlanefOES"); + jint _exception = 0; + GLfloat *eqn_base = (GLfloat *) 0; + jint _remaining; + GLfloat *eqn = (GLfloat *) 0; + + if (!eqn_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "eqn == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(eqn_ref) - offset; + if (_remaining < 4) { + _exception = 1; + _env->ThrowNew(IAEClass, "length - offset < 4"); + goto exit; + } + eqn_base = (GLfloat *) + _env->GetPrimitiveArrayCritical(eqn_ref, (jboolean *)0); + eqn = eqn_base + offset; + + glGetClipPlanefOES( + (GLenum)pname, + (GLfloat *)eqn + ); + +exit: + if (eqn_base) { + _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn ) */ static void android_glGetClipPlanefOES__ILjava_nio_FloatBuffer_2 (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) { - _env->ThrowNew(UOEClass, - "glGetClipPlanefOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfloat *eqn = (GLfloat *) 0; + + eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining); + if (_remaining < 4) { + _exception = 1; + _env->ThrowNew(IAEClass, "remaining() < 4"); + goto exit; + } + glGetClipPlanefOES( + (GLenum)pname, + (GLfloat *)eqn + ); + +exit: + if (_array) { + releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glClearDepthfOES ( GLclampf depth ) */ static void android_glClearDepthfOES__F (JNIEnv *_env, jobject _this, jfloat depth) { - _env->ThrowNew(UOEClass, - "glClearDepthfOES"); + glClearDepthfOES( + (GLclampf)depth + ); } /* void glTexGenfOES ( GLenum coord, GLenum pname, GLfloat param ) */ static void android_glTexGenfOES__IIF (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloat param) { - _env->ThrowNew(UOEClass, - "glTexGenfOES"); + glTexGenfOES( + (GLenum)coord, + (GLenum)pname, + (GLfloat)param + ); } /* void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params ) */ static void android_glTexGenfvOES__II_3FI (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glTexGenfvOES"); + GLfloat *params_base = (GLfloat *) 0; + jint _remaining; + GLfloat *params = (GLfloat *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfloat *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glTexGenfvOES( + (GLenum)coord, + (GLenum)pname, + (GLfloat *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params ) */ static void android_glTexGenfvOES__IILjava_nio_FloatBuffer_2 (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glTexGenfvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfloat *params = (GLfloat *) 0; + + params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining); + glTexGenfvOES( + (GLenum)coord, + (GLenum)pname, + (GLfloat *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glTexGeniOES ( GLenum coord, GLenum pname, GLint param ) */ static void android_glTexGeniOES__III (JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glTexGeniOES"); + glTexGeniOES( + (GLenum)coord, + (GLenum)pname, + (GLint)param + ); } /* void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params ) */ static void android_glTexGenivOES__II_3II (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glTexGenivOES"); + GLint *params_base = (GLint *) 0; + jint _remaining; + GLint *params = (GLint *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLint *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glTexGenivOES( + (GLenum)coord, + (GLenum)pname, + (GLint *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params ) */ static void android_glTexGenivOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glTexGenivOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLint *params = (GLint *) 0; + + params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining); + glTexGenivOES( + (GLenum)coord, + (GLenum)pname, + (GLint *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glTexGenxOES ( GLenum coord, GLenum pname, GLfixed param ) */ static void android_glTexGenxOES__III (JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) { - _env->ThrowNew(UOEClass, - "glTexGenxOES"); + glTexGenxOES( + (GLenum)coord, + (GLenum)pname, + (GLfixed)param + ); } /* void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params ) */ static void android_glTexGenxvOES__II_3II (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glTexGenxvOES"); + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glTexGenxvOES( + (GLenum)coord, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + JNI_ABORT); + } } /* void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params ) */ static void android_glTexGenxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glTexGenxvOES"); + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glTexGenxvOES( + (GLenum)coord, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, JNI_FALSE); + } } /* void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params ) */ static void android_glGetTexGenfvOES__II_3FI (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetTexGenfvOES"); + jint _exception = 0; + GLfloat *params_base = (GLfloat *) 0; + jint _remaining; + GLfloat *params = (GLfloat *) 0; + + if (!params_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfloat *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glGetTexGenfvOES( + (GLenum)coord, + (GLenum)pname, + (GLfloat *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params ) */ static void android_glGetTexGenfvOES__IILjava_nio_FloatBuffer_2 (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glGetTexGenfvOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfloat *params = (GLfloat *) 0; + + params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining); + glGetTexGenfvOES( + (GLenum)coord, + (GLenum)pname, + (GLfloat *)params + ); + if (_array) { + releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params ) */ static void android_glGetTexGenivOES__II_3II (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetTexGenivOES"); + jint _exception = 0; + GLint *params_base = (GLint *) 0; + jint _remaining; + GLint *params = (GLint *) 0; + + if (!params_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLint *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glGetTexGenivOES( + (GLenum)coord, + (GLenum)pname, + (GLint *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params ) */ static void android_glGetTexGenivOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glGetTexGenivOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLint *params = (GLint *) 0; + + params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining); + glGetTexGenivOES( + (GLenum)coord, + (GLenum)pname, + (GLint *)params + ); + if (_array) { + releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE); + } } /* void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params ) */ static void android_glGetTexGenxvOES__II_3II (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) { - _env->ThrowNew(UOEClass, - "glGetTexGenxvOES"); + jint _exception = 0; + GLfixed *params_base = (GLfixed *) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + if (!params_ref) { + _exception = 1; + _env->ThrowNew(IAEClass, "params == null"); + goto exit; + } + if (offset < 0) { + _exception = 1; + _env->ThrowNew(IAEClass, "offset < 0"); + goto exit; + } + _remaining = _env->GetArrayLength(params_ref) - offset; + params_base = (GLfixed *) + _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0); + params = params_base + offset; + + glGetTexGenxvOES( + (GLenum)coord, + (GLenum)pname, + (GLfixed *)params + ); + +exit: + if (params_base) { + _env->ReleasePrimitiveArrayCritical(params_ref, params_base, + _exception ? JNI_ABORT: 0); + } } /* void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params ) */ static void android_glGetTexGenxvOES__IILjava_nio_IntBuffer_2 (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) { - _env->ThrowNew(UOEClass, - "glGetTexGenxvOES"); + jint _exception = 0; + jarray _array = (jarray) 0; + jint _remaining; + GLfixed *params = (GLfixed *) 0; + + params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining); + glGetTexGenxvOES( + (GLenum)coord, + (GLenum)pname, + (GLfixed *)params + ); + if (_array) { + releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE); + } } static const char *classPathName = "android/opengl/GLES11Ext"; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 9f6ebed..caa1318 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -366,6 +366,23 @@ android:label="@string/permlab_readPhoneState" android:description="@string/permdesc_readPhoneState" /> + <!-- ================================== --> + <!-- Permissions for sdcard interaction --> + <!-- ================================== --> + <eat-comment /> + + <!-- Group of permissions that are related to SD card access. --> + <permission-group android:name="android.permission-group.STORAGE" + android:label="@string/permgrouplab_storage" + android:description="@string/permgroupdesc_storage" /> + + <!-- Allows an application to write to the SD card --> + <permission android:name="android.permission.SDCARD_WRITE" + android:permissionGroup="android.permission-group.STORAGE" + android:label="@string/permlab_sdcardWrite" + android:description="@string/permdesc_sdcardWrite" + android:protectionLevel="normal" /> + <!-- ============================================ --> <!-- Permissions for low-level system interaction --> <!-- ============================================ --> diff --git a/core/res/res/drawable/btn_global_search.xml b/core/res/res/drawable/btn_global_search.xml new file mode 100644 index 0000000..531f07e --- /dev/null +++ b/core/res/res/drawable/btn_global_search.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- TODO Need different assets for some of these button states. --> + <item android:state_window_focused="false" android:state_enabled="true" + android:drawable="@drawable/btn_global_search_normal" /> + <item android:state_window_focused="false" android:state_enabled="false" + android:drawable="@drawable/btn_global_search_normal" /> + <item android:state_pressed="true" + android:drawable="@drawable/btn_default_pressed" /> + <item android:state_focused="true" android:state_enabled="true" + android:drawable="@drawable/btn_default_selected" /> + <item android:state_enabled="true" + android:drawable="@drawable/btn_global_search_normal" /> + <item android:state_focused="true" + android:drawable="@drawable/btn_global_search_normal" /> + <item + android:drawable="@drawable/btn_global_search_normal" /> +</selector> diff --git a/core/res/res/drawable/btn_global_search_normal.9.png b/core/res/res/drawable/btn_global_search_normal.9.png Binary files differnew file mode 100644 index 0000000..9b7d3e5 --- /dev/null +++ b/core/res/res/drawable/btn_global_search_normal.9.png diff --git a/core/res/res/drawable/btn_search_dialog.xml b/core/res/res/drawable/btn_search_dialog.xml new file mode 100644 index 0000000..b7f5187 --- /dev/null +++ b/core/res/res/drawable/btn_search_dialog.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:state_window_focused="false" android:state_enabled="true" + android:drawable="@drawable/btn_search_dialog_default" /> + + <item android:state_pressed="true" + android:drawable="@drawable/btn_search_dialog_pressed" /> + + <item android:state_focused="true" android:state_enabled="true" + android:drawable="@drawable/btn_search_dialog_selected" /> + + <item android:state_enabled="true" + android:drawable="@drawable/btn_search_dialog_default" /> + + <item + android:drawable="@drawable/btn_search_dialog_default" /> +</selector> diff --git a/core/res/res/drawable/btn_search_dialog_default.9.png b/core/res/res/drawable/btn_search_dialog_default.9.png Binary files differnew file mode 100644 index 0000000..ec39178 --- /dev/null +++ b/core/res/res/drawable/btn_search_dialog_default.9.png diff --git a/core/res/res/drawable/btn_search_dialog_pressed.9.png b/core/res/res/drawable/btn_search_dialog_pressed.9.png Binary files differnew file mode 100644 index 0000000..5f52fef --- /dev/null +++ b/core/res/res/drawable/btn_search_dialog_pressed.9.png diff --git a/core/res/res/drawable/btn_search_dialog_selected.9.png b/core/res/res/drawable/btn_search_dialog_selected.9.png Binary files differnew file mode 100644 index 0000000..9fc2fde --- /dev/null +++ b/core/res/res/drawable/btn_search_dialog_selected.9.png diff --git a/core/res/res/drawable/btn_search_dialog_voice.xml b/core/res/res/drawable/btn_search_dialog_voice.xml new file mode 100644 index 0000000..748aaf5 --- /dev/null +++ b/core/res/res/drawable/btn_search_dialog_voice.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:state_window_focused="false" android:state_enabled="true" + android:drawable="@drawable/btn_search_dialog_voice_default" /> + + <item android:state_pressed="true" + android:drawable="@drawable/btn_search_dialog_voice_pressed" /> + + <item android:state_focused="true" android:state_enabled="true" + android:drawable="@drawable/btn_search_dialog_voice_selected" /> + + <item android:state_enabled="true" + android:drawable="@drawable/btn_search_dialog_voice_default" /> + + <item + android:drawable="@drawable/btn_search_dialog_voice_default" /> +</selector> diff --git a/core/res/res/drawable/btn_search_dialog_voice_default.9.png b/core/res/res/drawable/btn_search_dialog_voice_default.9.png Binary files differnew file mode 100644 index 0000000..2a3366c --- /dev/null +++ b/core/res/res/drawable/btn_search_dialog_voice_default.9.png diff --git a/core/res/res/drawable/btn_search_dialog_voice_pressed.9.png b/core/res/res/drawable/btn_search_dialog_voice_pressed.9.png Binary files differnew file mode 100644 index 0000000..57d7a74 --- /dev/null +++ b/core/res/res/drawable/btn_search_dialog_voice_pressed.9.png diff --git a/core/res/res/drawable/btn_search_dialog_voice_selected.9.png b/core/res/res/drawable/btn_search_dialog_voice_selected.9.png Binary files differnew file mode 100644 index 0000000..db3187e --- /dev/null +++ b/core/res/res/drawable/btn_search_dialog_voice_selected.9.png diff --git a/core/res/res/drawable/search_dropdown_background.9.png b/core/res/res/drawable/search_dropdown_background.9.png Binary files differnew file mode 100755 index 0000000..a6923b7 --- /dev/null +++ b/core/res/res/drawable/search_dropdown_background.9.png diff --git a/core/res/res/drawable/search_plate_global.9.png b/core/res/res/drawable/search_plate_global.9.png Binary files differnew file mode 100644 index 0000000..126054b --- /dev/null +++ b/core/res/res/drawable/search_plate_global.9.png diff --git a/core/res/res/drawable/textfield_search.xml b/core/res/res/drawable/textfield_search.xml new file mode 100644 index 0000000..2923368 --- /dev/null +++ b/core/res/res/drawable/textfield_search.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:state_window_focused="false" android:state_enabled="true" + android:drawable="@drawable/textfield_search_default" /> + + <item android:state_pressed="true" + android:drawable="@drawable/textfield_search_pressed" /> + + <item android:state_enabled="true" android:state_focused="true" + android:drawable="@drawable/textfield_search_selected" /> + + <item android:drawable="@drawable/textfield_search_default" /> + +</selector> + diff --git a/core/res/res/drawable/textfield_search_default.9.png b/core/res/res/drawable/textfield_search_default.9.png Binary files differnew file mode 100755 index 0000000..7dc5b27 --- /dev/null +++ b/core/res/res/drawable/textfield_search_default.9.png diff --git a/core/res/res/drawable/textfield_search_pressed.9.png b/core/res/res/drawable/textfield_search_pressed.9.png Binary files differnew file mode 100644 index 0000000..da00c25 --- /dev/null +++ b/core/res/res/drawable/textfield_search_pressed.9.png diff --git a/core/res/res/drawable/textfield_search_selected.9.png b/core/res/res/drawable/textfield_search_selected.9.png Binary files differnew file mode 100755 index 0000000..a9fd3b2 --- /dev/null +++ b/core/res/res/drawable/textfield_search_selected.9.png diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml index 5e296c5..4c5c456 100644 --- a/core/res/res/layout/resolve_list_item.xml +++ b/core/res/res/layout/resolve_list_item.xml @@ -23,7 +23,7 @@ android:minHeight="?android:attr/listPreferredItemHeight" android:layout_height="wrap_content" android:layout_width="fill_parent" - android:paddingLeft="14dip" + android:paddingLeft="10dip" android:paddingRight="15dip"> <!-- Activity icon when presenting dialog --> @@ -42,13 +42,13 @@ android:textAppearance="?android:attr/textAppearanceLargeInverse" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingLeft="6dip" /> + android:paddingLeft="10dip" /> <!-- Extended activity info to distinguish between duplicate activity names --> <TextView android:id="@android:id/text2" android:textAppearance="?android:attr/textAppearanceMediumInverse" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingLeft="6dip" /> + android:paddingLeft="10dip" /> </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml index ef347da..6155626 100644 --- a/core/res/res/layout/search_bar.xml +++ b/core/res/res/layout/search_bar.xml @@ -26,79 +26,67 @@ android:orientation="vertical" android:focusable="true" android:descendantFocusability="afterDescendants"> - <!-- android:paddingBottom="14dip" TODO MUST FIX - it's a hack to get the popup to show --> + <!-- android:paddingBottom="200dip" TODO MUST FIX - it's a hack to get the popup to show --> <!-- Outer layout defines the entire search bar at the top of the screen --> - <!-- Bottom padding of 16 is due to the graphic, with 9 extra pixels of drop - shadow, plus the desired padding of "8" against the user-visible (grey) - pixels, minus "1" to correct for positioning of the edittext & button. --> <LinearLayout android:id="@+id/search_plate" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:paddingLeft="8dip" - android:paddingRight="8dip" - android:paddingTop="6dip" + android:paddingLeft="12dip" + android:paddingRight="12dip" + android:paddingTop="7dip" android:paddingBottom="16dip" - android:baselineAligned="false" - android:background="@android:drawable/search_plate" - android:addStatesFromChildren="true" > + android:background="@drawable/search_plate_global" > <!-- This is actually used for the badge icon *or* the badge label (or neither) --> <TextView android:id="@+id/search_badge" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingLeft="2dip" + android:layout_marginBottom="2dip" android:drawablePadding="0dip" android:textAppearance="?android:attr/textAppearanceSmall" - android:textColor="?android:attr/textColorPrimary" /> + android:textColor="?android:attr/textColorPrimaryInverse" /> <!-- Inner layout contains the button(s) and EditText --> - <!-- The layout_marginTop of "1" corrects for the extra 1 pixel of padding at the top of - textfield_selected.9.png. The "real" margin as displayed is "2". --> - <!-- The layout_marginBottom of "-5" corrects for the spacing we see at the - bottom of the edittext and button images. The "real" margin as displayed is "8" --> <LinearLayout android:id="@+id/search_edit_frame" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_marginTop="1dip" - android:layout_marginBottom="-5dip" - android:orientation="horizontal" - android:addStatesFromChildren="true" - android:gravity="center_vertical" - android:baselineAligned="false" > - + android:orientation="horizontal"> + <view class="android.app.SearchDialog$SearchAutoComplete" android:id="@+id/search_src_text" + android:background="@drawable/textfield_search" android:layout_height="wrap_content" android:layout_width="0dip" android:layout_weight="1.0" android:paddingLeft="8dip" android:paddingRight="6dip" + android:singleLine="true" android:inputType="text|textAutoComplete" android:dropDownWidth="fill_parent" android:dropDownAnchor="@id/search_plate" - android:dropDownVerticalOffset="-15dip" + android:dropDownVerticalOffset="-9dip" + android:popupBackground="@android:drawable/search_dropdown_background" /> - <!-- android:focusableInTouchMode="false" --> - <!-- android:singleLine="true" --> - <!-- android:selectAllOnFocus="true" --> <!-- This button can switch between text and icon "modes" --> <Button android:id="@+id/search_go_btn" - android:layout_marginLeft="1dip" + android:background="@drawable/btn_search_dialog" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:drawableLeft="@android:drawable/ic_btn_search" + android:layout_height="fill_parent" /> - <ImageButton android:id="@+id/search_voice_btn" + <ImageButton + android:id="@+id/search_voice_btn" android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_height="fill_parent" + android:layout_marginLeft="8dip" + android:background="@drawable/btn_search_dialog_voice" android:src="@android:drawable/ic_btn_speak_now" /> </LinearLayout> diff --git a/core/res/res/layout/search_dropdown_item_1line.xml b/core/res/res/layout/search_dropdown_item_1line.xml index 3827206..bf3dd48 100644 --- a/core/res/res/layout/search_dropdown_item_1line.xml +++ b/core/res/res/layout/search_dropdown_item_1line.xml @@ -20,7 +20,7 @@ <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceMediumInverse" + android:textAppearance="?android:attr/textAppearanceSearchResultTitle" android:singleLine="true" android:layout_width="fill_parent" - android:layout_height="?android:attr/listPreferredItemHeight" /> + android:layout_height="?android:attr/searchResultListItemHeight" />
\ No newline at end of file diff --git a/core/res/res/layout/search_dropdown_item_2line.xml b/core/res/res/layout/search_dropdown_item_2line.xml index 96d6005..5546b6636 100644 --- a/core/res/res/layout/search_dropdown_item_2line.xml +++ b/core/res/res/layout/search_dropdown_item_2line.xml @@ -20,15 +20,16 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" - android:layout_height="?android:attr/listPreferredItemHeight" + android:layout_height="?android:attr/searchResultListItemHeight" android:orientation="horizontal" android:gravity="center_vertical" android:baselineAligned="false" > <TwoLineListItem - android:paddingTop="2dip" - android:paddingBottom="2dip" + android:paddingTop="1dip" + android:paddingBottom="1dip" + android:gravity="center_vertical" android:layout_width="0dip" android:layout_weight="1" android:layout_height="wrap_content" @@ -37,7 +38,7 @@ <TextView android:id="@android:id/text1" style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceMediumInverse" + android:textAppearance="?android:attr/textAppearanceSearchResultTitle" android:singleLine="true" android:layout_width="fill_parent" android:layout_height="wrap_content" /> @@ -45,7 +46,7 @@ <TextView android:id="@android:id/text2" style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceSmallInverse" + android:textAppearance="?android:attr/textAppearanceSearchResultSubtitle" android:textColor="?android:attr/textColorSecondaryInverse" android:singleLine="true" android:layout_width="fill_parent" diff --git a/core/res/res/layout/search_dropdown_item_icons_1line.xml b/core/res/res/layout/search_dropdown_item_icons_1line.xml index c0713d5..4f65d74 100644 --- a/core/res/res/layout/search_dropdown_item_icons_1line.xml +++ b/core/res/res/layout/search_dropdown_item_icons_1line.xml @@ -22,31 +22,33 @@ <!-- of the text element in apps/common/res/layout/simple_dropdown_item_1line.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:paddingLeft="4dip" + android:paddingRight="2dip" android:layout_width="fill_parent" - android:layout_height="?android:attr/listPreferredItemHeight" + android:layout_height="?android:attr/searchResultListItemHeight" android:orientation="horizontal" android:gravity="center_vertical" android:baselineAligned="false" > <ImageView android:id="@android:id/icon1" - android:layout_width="32dip" - android:layout_height="32dip" + android:layout_width="48dip" + android:layout_height="48dip" android:layout_gravity="center_vertical" - android:scaleType="fitCenter" /> + android:scaleType="centerInside" /> <TextView android:id="@android:id/text1" style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceMediumInverse" + android:textAppearance="?android:attr/textAppearanceSearchResultTitle" android:singleLine="true" android:layout_height="wrap_content" android:layout_width="0dip" android:layout_weight="1" /> <ImageView android:id="@android:id/icon2" - android:layout_width="32dip" - android:layout_height="32dip" + android:layout_width="48dip" + android:layout_height="48dip" android:layout_gravity="center_vertical" - android:scaleType="fitCenter" /> + android:scaleType="centerInside" /> </LinearLayout> diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml index ad1c905..0d07490 100644 --- a/core/res/res/layout/search_dropdown_item_icons_2line.xml +++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/assets/res/any/layout/simple_spinner_item.xml +/* ** ** Copyright 2008, The Android Open Source Project ** @@ -18,56 +18,62 @@ */ --> - <!-- NOTE: The appearance of the inner text element must match the appearance --> - <!-- of the text element in apps/common/res/layout/simple_dropdown_item_2line.xml --> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:paddingLeft="4dip" + android:paddingRight="2dip" android:layout_width="fill_parent" - android:layout_height="?android:attr/listPreferredItemHeight" - android:orientation="horizontal" - android:gravity="center_vertical" - android:baselineAligned="false" - > - - <ImageView android:id="@android:id/icon1" - android:layout_width="32dip" - android:layout_height="32dip" - android:layout_gravity="center_vertical" - android:scaleType="fitCenter" /> + android:layout_height="?android:attr/searchResultListItemHeight" > - <TwoLineListItem - android:paddingTop="2dip" - android:paddingBottom="2dip" - android:layout_width="0dip" - android:layout_weight="1" - android:layout_height="wrap_content" - android:mode="twoLine" > - - <TextView - android:id="@android:id/text1" - style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceMediumInverse" - android:singleLine="true" - android:layout_width="fill_parent" - android:layout_height="wrap_content" /> - - <TextView - android:id="@android:id/text2" - style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceSmallInverse" - android:textColor="?android:attr/textColorSecondaryInverse" - android:singleLine="true" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_below="@android:id/text1" - android:layout_alignLeft="@android:id/text1" /> - - </TwoLineListItem> + <!-- Icons come first in the layout, since their placement doesn't depend on + the placement of the text views. --> + <ImageView android:id="@android:id/icon1" + android:layout_width="48dip" + android:layout_height="48dip" + android:scaleType="centerInside" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:layout_alignParentBottom="true" + android:visibility="gone" /> <ImageView android:id="@android:id/icon2" - android:layout_width="32dip" - android:layout_height="32dip" - android:layout_gravity="center_vertical" - android:scaleType="fitCenter" /> + android:layout_width="48dip" + android:layout_height="48dip" + android:scaleType="centerInside" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_alignParentBottom="true" + android:visibility="gone" /> -</LinearLayout> + <!-- The subtitle comes before the title, since the height of the title depends on whether the + subtitle is visible or gone. --> + <TextView android:id="@android:id/text2" + style="?android:attr/dropDownItemStyle" + android:textAppearance="?android:attr/textAppearanceSearchResultSubtitle" + android:singleLine="true" + android:layout_width="fill_parent" + android:layout_height="29dip" + android:paddingBottom="4dip" + android:gravity="top" + android:layout_toRightOf="@android:id/icon1" + android:layout_toLeftOf="@android:id/icon2" + android:layout_alignWithParentIfMissing="true" + android:layout_alignParentBottom="true" + android:visibility="gone" /> + + <!-- The title is placed above the subtitle, if there is one. If there is no + subtitle, it fills the parent. --> + <TextView android:id="@android:id/text1" + style="?android:attr/dropDownItemStyle" + android:textAppearance="?android:attr/textAppearanceSearchResultTitle" + android:singleLine="true" + android:layout_width="fill_parent" + android:layout_height="29dip" + android:paddingTop="4dip" + android:gravity="center_vertical" + android:layout_alignParentTop="true" + android:layout_toRightOf="@android:id/icon1" + android:layout_toLeftOf="@android:id/icon2" + android:layout_above="@android:id/text2" + android:layout_alignWithParentIfMissing="true" /> + +</RelativeLayout> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index b98558e..972953b 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -94,6 +94,11 @@ <!-- Text color, typeface, size, and style for "small" inverse text. Defaults to secondary inverse text color. --> <attr name="textAppearanceSmallInverse" format="reference" /> + <!-- Text color, typeface, size, and style for system search result title. Defaults to primary inverse text color. @hide --> + <attr name="textAppearanceSearchResultTitle" format="reference" /> + <!-- Text color, typeface, size, and style for system search result subtitle. Defaults to primary inverse text color. @hide --> + <attr name="textAppearanceSearchResultSubtitle" format="reference" /> + <!-- Text color, typeface, size, and style for the text inside of a button. --> <attr name="textAppearanceButton" format="reference" /> @@ -147,6 +152,8 @@ <!-- The preferred list item height --> <attr name="listPreferredItemHeight" format="dimension" /> <!-- The drawable for the list divider --> + <!-- The list item height for search results. @hide --> + <attr name="searchResultListItemHeight" format="dimension" /> <attr name="listDivider" format="reference" /> <!-- TextView style for list separators. --> <attr name="listSeparatorTextViewStyle" format="reference" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 8150a96..c35676c 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -335,6 +335,11 @@ <string name="permgroupdesc_developmentTools">Features only needed for application developers.</string> + <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permgrouplab_storage">Storage</string> + <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permgroupdesc_storage">Access the SD card.</string> + <!-- Permissions --> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> @@ -1045,6 +1050,11 @@ <string name="permdesc_writeDictionary">Allows an application to write new words into the user dictionary.</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_sdcardWrite">write to SD card</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_sdcardWrite">Allows an application to write to the SD card.</string> + <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip /> <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. --> <string-array name="phoneTypes"> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index d7b654e..a436f61 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -138,6 +138,7 @@ </style> <!-- Window animations that are applied to the search bar overlay window. + Previously used, but currently unused. {@hide Pending API council approval} --> <style name="Animation.SearchBar"> <item name="windowEnterAnimation">@anim/search_bar_enter</item> @@ -574,6 +575,24 @@ <item name="android:textColor">@android:color/primary_text_light_disable_only</item> </style> + <!-- @hide --> + <style name="TextAppearance.SearchResult"> + <item name="android:textStyle">normal</item> + <item name="android:textColor">?textColorPrimaryInverse</item> + <item name="android:textColorHint">?textColorHintInverse</item> + </style> + + <!-- @hide --> + <style name="TextAppearance.SearchResult.Title"> + <item name="android:textSize">16sp</item> + </style> + + <!-- @hide --> + <style name="TextAppearance.SearchResult.Subtitle"> + <item name="android:textSize">13sp</item> + <item name="android:textColor">?textColorSecondaryInverse</item> + </style> + <style name="TextAppearance.WindowTitle"> <item name="android:textColor">#fff</item> <item name="android:textSize">14sp</item> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 6b3d740..dfd2391 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -57,6 +57,12 @@ <item name="textAppearanceLargeInverse">@android:style/TextAppearance.Large.Inverse</item> <item name="textAppearanceMediumInverse">@android:style/TextAppearance.Medium.Inverse</item> <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Small.Inverse</item> + + <!-- @hide --> + <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.SearchResult.Title</item> + + <!-- @hide --> + <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.SearchResult.Subtitle</item> <item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item> @@ -75,6 +81,8 @@ <!-- List attributes --> <item name="listPreferredItemHeight">64dip</item> + <!-- @hide --> + <item name="searchResultListItemHeight">58dip</item> <item name="listDivider">@drawable/divider_horizontal_dark</item> <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator</item> @@ -355,7 +363,6 @@ <!-- Theme for the search input bar. --> <style name="Theme.SearchBar" parent="Theme.Panel"> <item name="android:backgroundDimEnabled">true</item> - <item name="android:windowAnimationStyle">@android:style/Animation.SearchBar</item> <item name="windowContentOverlay">@null</item> </style> diff --git a/data/etc/platform.xml b/data/etc/platform.xml index b13a292..f80bd6b 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -54,6 +54,10 @@ <group gid="log" /> </permission> + <permission name="android.permission.SDCARD_WRITE" > + <group gid="sdcard_rw" /> + </permission> + <!-- The group that /cache belongs to, linked to the permission set on the applications that can access /cache --> <permission name="android.permission.ACCESS_CACHE_FILESYSTEM" > diff --git a/docs/html/community/index.jd b/docs/html/community/index.jd index 2df4c01..ad3a199 100644 --- a/docs/html/community/index.jd +++ b/docs/html/community/index.jd @@ -77,7 +77,7 @@ phrasing your questions, read <a href="http://www.catb.org/%7Eesr/faqs/smart-que <li><b>Android security discuss</b> - A place for open discussion on secure development, emerging security concerns, and best practices for and by android developers. Please don't disclose vulnerabilities directly on this list, you'd be putting all Android users at risk. <ul> <li>Subscribe using Google Groups: <a href="http://groups.google.com/group/android-security-discuss">android-security-discuss</a></li> -<li>Subscribe via email: <a href="mailto:android-security-discuss@googlegroups.com">android-secuirty-discuss@googlegroups.com</a><a href="mailto:android-platform-subscribe@googlegroups.com"> +<li>Subscribe via email: <a href="mailto:android-security-discuss@googlegroups.com">android-security-discuss@googlegroups.com</a><a href="mailto:android-platform-subscribe@googlegroups.com"> </a></li> </ul> </li> diff --git a/docs/html/guide/appendix/faq/framework.jd b/docs/html/guide/appendix/faq/framework.jd index 76a19c5..33b69ac 100644 --- a/docs/html/guide/appendix/faq/framework.jd +++ b/docs/html/guide/appendix/faq/framework.jd @@ -12,7 +12,7 @@ parent.link=index.html from one Activity/Service to another?</a></li> <li><a href="#4">How can I check if an Activity is already running before starting it?</a></li> - <li><a href="#5">If an Activity starts a remote service,is + <li><a href="#5">If an Activity starts a remote service, is there any way for the Service to pass a message back to the Activity?</a></li> <li><a href="#6">How to avoid getting the Application not responding dialog?</a></li> @@ -20,7 +20,6 @@ parent.link=index.html added or removed?</a></li> </ul> -<!-- ------------------------------------------------------------------ --> <a name="1" id="1"></a> @@ -32,7 +31,7 @@ default. If needed, you can declare an <code>android:process</code> attribute in your manifest file, to explicitly place a component (Activity/Service) in another process.</p> -<!-- ------------------------------------------------------------------ --> + <a name="2" id="2"></a> @@ -47,7 +46,7 @@ separate pool of transaction threads in each process to dispatch all incoming IPC calls. The developer should create separate threads for any long-running code, to avoid blocking the main UI thread.</p> -<!-- ------------------------------------------------------------------ --> + <a name="3" id="3"></a> @@ -128,7 +127,7 @@ the <a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a> for further details on how to use these components.</p> -<!-- ------------------------------------------------------------------ --> + <a name="4" id="4"></a> @@ -140,7 +139,7 @@ or to bring the activity stack to the front if is already running in the background— is the to use the NEW_TASK_LAUNCH flag in the startActivity() call.</p> -<!-- ------------------------------------------------------------------ --> + <a name="5" id="5"></a> @@ -156,7 +155,7 @@ messages.</p> <p>The sample code for remote service callbacks is given in <a href="{@docRoot}guide/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">ApiDemos/RemoteService</a></p> -<!-- ------------------------------------------------------------------ --> + <a name="6" id="6"></a> @@ -166,7 +165,7 @@ href="{@docRoot}guide/samples/ApiDemos/src/com/example/android/apis/app/RemoteSe document.</p> -<!-- ------------------------------------------------------------------ --> + <a name="7" id="7"></a> @@ -194,5 +193,5 @@ removed. </p> -<!-- ------------------------------------------------------------------ --> + diff --git a/docs/html/guide/appendix/faq/troubleshooting.jd b/docs/html/guide/appendix/faq/troubleshooting.jd index 7c703e6..0cf1ab0 100644 --- a/docs/html/guide/appendix/faq/troubleshooting.jd +++ b/docs/html/guide/appendix/faq/troubleshooting.jd @@ -23,7 +23,6 @@ parent.link=index.html <li><a href="#majorminor">When I go to preferences in Eclipse and select "Android", I get the following error message: Unsupported major.minor version 49.0.</a></li> <li><a href="#apidemosreinstall">I can't install ApiDemos apps in my IDE because of a signing error</a></li> <li><a href="#signingcalendar">I can't compile my app because the build tools generated an expired debug certificate</a></li> - <li><a href="#addjunit">I can't run a JUnit test class in Eclipse/ADT</a></li> </ul> <a name="installeclipsecomponents" id="installeclipsecomponents"></a><h2>ADT Installation Error: "requires plug-in org.eclipse.wst.sse.ui".</h2> @@ -245,8 +244,8 @@ documentation.</p> <ol> <li>First, delete the debug keystore/key already generated by the Android build tools. Specifically, delete the <code>debug.keystore</code> file. On Linux/Mac OSX, the file is stored in <code>~/.android</code>. On Windows XP, the file is stored in <code> -C:\Documents and Settings\<user>\Local Settings\Application Data\Android</code>. On Windows Vista, the file is stored in <code> -C:\Users\<user>\AppData\Local\Android</code></li> +C:\Documents and Settings\<user>\.android</code>. On Windows Vista, the file is stored in <code> +C:\Users\<user>\.android</code></li> <li>Next, you can either <ul> <li>Temporarily change your development machine's locale (date and time) to one that uses a Gregorian calendar, for example, United States. Once the locale is changed, use the Android build tools to compile and install your app. The build tools will regenerate a new keystore and debug key with valid dates. Once the new debug key is generated, you can reset your development machine to the original locale. </li> @@ -260,46 +259,3 @@ C:\Users\<user>\AppData\Local\Android</code></li> <p>For general information about signing Android applications, see <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>. </p> -<h2 id="addjunit">I can't run a JUnit test class in Eclipse/ADT</h2> - -<p>If you are developing on Eclipse/ADT, you can add JUnit test classes to your application. However, you may get an error when trying to run such a class as a JUnit test:</p> - -<pre>Error occurred during initialization of VM -java/lang/NoClassDefFoundError: java/lang/ref/FinalReference</pre> - -<p>This error occurs because android.jar does not include complete Junit.* class implementations, but includes stub classes only. </p> - -<p>To add a JUnit class, you have to set up a JUnit configuration:. - -<ol> -<li>In the Package Explorer view, select your project. </li> -<li>Open the launch configuration manager. - <ul> - <li>In Eclipse 3.3 (Europa), select <strong>Run </strong>> - <strong>Open Run Dialog... </strong>or <strong>Run </strong>> - <strong>Open Debug Dialog... </strong>. - </li> - - <li>In Eclipse 3.4 (Ganymede), select <strong>Run </strong>> - <strong>Run Configurations... </strong>or <strong>Run </strong>> - <strong>Debug Configurations... </strong>. - </li> - </ul> - </li> -<li>In the configuration manager, right-click the "JUnit" configuration type and select <strong>New</strong></li> -<li>In the new configuration's <strong>Test</strong> tab, specify the project and test class, as well as any options for running the test. </li> -<li>In the new configuration's <strong>Classpath</strong> tab, find "Android Library" under Bootstrap Entries and remove it. </li> -<li>Still in the <strong>Classpath</strong> tab, select Bootstrap Entries and click the Advanced button. </li> -<ol type="a"> -<li>Choose Add Library and click OK.</li> -<li>Select JRE System Library and click Next. </li> -<li>Select Workspace Default JRE and click Finish.</li> -</ol> -<li>Select Bootstrap Entries again and click Advanced.</li> -<ol type="a"> -<li>Choose Add Library and click OK.</li> -<li>Select JUnit 3 and click Finish. </li> -</ol> -</ol> -<p>When configured in this way, your JUnit test class should now run properly.</p> - diff --git a/docs/html/guide/developing/app-signing.jd b/docs/html/guide/developing/app-signing.jd deleted file mode 100644 index 582dfb2..0000000 --- a/docs/html/guide/developing/app-signing.jd +++ /dev/null @@ -1,428 +0,0 @@ -page.title=Signing Your Applications -@jd:body - -<p>The Android system requires that all installed applications be digitally -signed with a certificate whose private key is held by the application's -developer. The system uses the certificate as a means of identifying the author of -an application and establishing trust relationships between applications, rather -than for controlling which applications the user can install. The certificate -does not need to be signed by a certificate authority: it is perfectly -allowable, and typical, for Android applications to use self-signed -certificates.</p> - -<p>The important points to understand about signing Android applications are:</p> - -<ul> - <li>All applications <em>must</em> be signed. The system will not install an application -that is not signed.</li> - <li>You can use self-signed certificates to sign your applications. No certificate authority -is needed.</li> - <li>When you are ready to publish your application, you must sign it with a suitable private -key. You can not publish an application that is signed with the default key generated -by the SDK tools. - </li> - <li>The system tests a signer certificate's expiration date only at install time. If an -application's signer certificate expires after the application is installed, the application -will continue to function normally.</li> - <li>You can use standard tools — Keytool and Jarsigner — to generate keys and -sign your application .apk files.</li> -</ul> - -<p>The Android system will not install or run an application that is not signed appropriately. This -applies wherever the Android system is run, whether on an actual device or on the emulator. -For this reason, you must set up signing for your application before you will be able to -run or debug it on an emulator or device.</p> - -<p>The Android SDK tools assist you in signing your applications when debugging. Both the ADT Plugin -for Eclipse and the Ant build tool offer two signing modes — debug mode and release mode. - -<ul> -<li>In debug mode, the build tools use the Keytool utility, included in the JDK, to create -a keystore and key with a known alias and password. At each compilation, the tools then use -the debug key to sign the application .apk file. Because the password is known, the tools -don't need to prompt you for the keystore/key password each time you compile.</li> - -<li>When your application is ready for release, you compile it in release signing mode. -In this mode, the tools compile your .apk <em>without</em> signing it. You must then sign -the .apk manually — <span style="color:red">with your private key</span> — -using Jarsigner (or similar tool). If you do not have a suitable private key already, -you can run Keytool manually to generate your own keystore/key and then sign your -application with Jarsigner.</li> -</ul> - -<h2>Signing Strategies</h2> - -<p>Some aspects of application signing may affect how you approach the development -of your application, especially if you are planning to release multiple -applications. </p> - -<p>In general, the recommended strategy for all developers is to sign -all of your applications with the same certificate, throughout the expected -lifespan of your applications. There are several reasons why you should do so: </p> - -<ul> -<li>Application upgrade — As you release upgrades to your -application, you will want to sign the upgrades with the same certificate, if you -want users to upgrade seamlessly to the new version. When the system is -installing an update to an application, if any of the certificates in the -new version match any of the certificates in the old version, then the -system allows the update. If you sign the version without using a matching -certificate, you will also need to assign a different package name to the -application — in this case, the user installs the new version as a -completely new application. - -<li>Application modularity — The Android system allows applications that -are signed by the same certificate to run in the same process, if the -applications so request, so that the system treats them as a single application. -In this way you can deploy your application in modules, and users can update -each of the modules independently if needed.</li> - -<li>Code/data sharing through permissions — The Android system provides -signature-based permissions enforcement, so that an application can expose -functionality to another application that is signed with a specified -certificate. By signing multiple applications with the same certificate and -using signature-based permissions checks, your applications can share code and -data in a secure manner. </li> - -</li> - -</ul> - -<p>Another important consideration in determining your signing strategy is -how to set the validity period of the key that you will use to sign your -applications.</p> - -<ul> -<li>If you plan to support upgrades for a single application, you should ensure -that your key has a validity period that exceeds the expected lifespan of -that application. A validity period of 25 years or more is recommended. -When your key's validity period expires, users will no longer be -able to seamlessly upgrade to new versions of your application.</li> - -<li>If you will sign multiple distinct applications with the same key, -you should ensure that your key's validity period exceeds the expected -lifespan of <em>all versions of all of the applications</em>, including -dependent applications that may be added to the suite in the future. </li> - -<li>If you plan to publish your application(s) on Android Market, the -key you use to sign the application(s) must have a validity period -ending after 22 October 2033. The Market server enforces this requirement -to ensure that users can seamlessly upgrade Market applications when -new versions are available. </li> -</ul> - -<p>As you design your application, keep these points in mind and make sure to -use a <a href="#cert">suitable certificate</a> to sign your applications. </p> - -<h2 id="setup">Basic Setup for Signing</h2> - -<p>To support the generation of a keystore and debug key, you should first make sure that -Keytool is available to the SDK build -tools. In most cases, you can tell the SDK build tools how to find Keytool by making sure -that your JAVA_HOME environment variable is set and that it references a suitable JDK. -Alternatively, you can add the JDK version of Keytool to your PATH variable.</p> - -<p>If you are developing on a version of Linux that originally came with GNU Compiler for -Java, make sure that the system is using the JDK version of Keytool, rather than the gcj -version. If Keytool is already in your PATH, it might be pointing to a symlink at -/usr/bin/keytool. In this case, check the symlink target to make sure that it points -to the Keytool in the JDK.</p> - -<p>If you will release your application to the public, you will also need to have -the Jarsigner tool available on your machine. Both Jarsigner and Keytool are included -in the JDK. </p> - -<h2>Signing in Debug Mode</h2> - -<p>The Android build tools provide a debug signing mode that makes it easier for you -to develop and debug your application, while still meeting the Android system -requirement for signing your .apk when it is installed in the emulator or a device. </p> - -<p>If you are developing in Eclipse/ADT and have set up Keytool as described -above, signing in debug mode is enabled by default. When you run or debug your -application, ADT signs the .apk for you and installs it on the emulator. No -specific action on your part is needed, provided ADT has access to Keytool.</p> - -<p>If you use Ant to build your .apk files, debug signing mode -is enabled by default, assuming that you are using a build.xml file generated by the -activitycreator tool included in the latest SDK. When you run Ant against build.xml to -compile your app, the build script generates a keystore/key and signs the .apk for you. -No specific action on your part is needed.</p> - -<p>Note that you can not release your application to the public if it is signed only with -the debug key. </p> - -<h2>Signing for Public Release</h2> - -<p>When your application is ready for release to other users, you must:</p> -<ol> -<li>Compile the application in release mode</li> -<li>Obtain a suitable private key, and then</li> -<li>Sign the application with your private key</li> -<li>Secure your private key</li> -</ol> - -<p>The sections below provide information about these steps. </p> - -<h3>Compiling for Release</h3> - -<p>To prepare your application for release, you must first compile it in release mode. -In release mode, the Android build tools compile your application as usual, -but without signing it with the debug key. </p> - -<p>If you are developing in Eclipse/ADT, right-click the project in the Package -pane and select <strong>Android Tools</strong> > <strong>Export Application -Package</strong>. You can then specify the file location for the unsigned .apk. -Alternatively, you can follow the "Exporting the unsigned .apk" -link in the Manifest Editor overview page. </p> - -<p>If you are using Ant, all you need to do is specify the build target -"release" in the Ant command. For example, if you are running Ant from the -directory containing your build.xml file, the command would look like this:</p> - -<pre>$ ant release</pre> - -<p>The build script compiles the application .apk without signing it. - -<p>Note that you can not release your application unsigned, or signed with the debug key.</p> - -<h3 id="cert">Obtaining a Suitable Private Key</h3> - -<p>In preparation for signing your application, you must first ensure that -you have a suitable private key with which to sign. A suitable private -key is one that:</p> - -<ul> -<li>Is in your possession</li> -<li>Represents the personal, corporate, or organizational entity to be identified -with the application</li> -<li>Has a validity period that exceeds the expected lifespan of the application -or application suite. A validity period of more than 25 years is recommended. -<p>If you plan to publish your application(s) on Android Market, note that a -validity period ending after 22 October 2033 is a requirement. You can not upload an -application if it is signed with a key whose validity expires before that date. -</p></li> -<li>Is not the debug key generated by the Android SDK tools. </li> -</ul> - -<p>The key may be self-signed. If you do not have a suitable key, you must -generate one using Keytool. Make sure that you have Keytool available, as described -in <a href="#setup">Basic Setup</a>.</p> - -<p>To generate a self-signed key with Keytool, use the <code>keytool</code> -command and pass any of the options listed below (and any others, as -needed). </p> - -<p class="warning">Before you run Keytool, make sure to read <a -href="#secure-key">Securing Your Key</a> for a discussion of how to keep your -key secure and why doing so is critically important to you and to users. In -particular, when you are generating your key, you should select strong -passwords for both the keystore and key.</p> - -<table> -<tr> -<th>Keytool Option</th> -<th>Description</th> -</tr> -<tr> -<td><code>-genkey</code></td><td>Generate a key pair (public and private -keys)</td> -</tr> -<tr> -<td><code>-v</code></td><td>Enable verbose output.</td> -</tr> -<tr> -<td><code>-keystore <keystore-name>.keystore</code></td><td>A name -for the keystore containing the private key.</td> -</tr> -<tr> -<td><code>-storepass <password></code></td><td><p>A password for the -keystore.</p><p>As a security precaution, do not include this option -in your command line unless you are working at a secure computer. -If not supplied, Keytool prompts you to enter the password. In this -way, your password is not stored in your shell history.</p></td> -</tr> -<tr> -<td><code>-alias <alias_name></code></td><td>An alias for the key.</td> -</tr> -<tr> -<td><code>-keyalg <alg></code></td><td>The encryption algorithm to use -when generating the key.</td> -</tr> -<tr> -<td><code>-dname <name></code></td><td><p>A Distinguished Name that describes -who created the key. The value is used as the issuer and subject fields in the -self-signed certificate. </p><p>Note that you do not need to specify this option -in the command line. If not supplied, Jarsigner prompts you to enter each -of the Distinguished Name fields (CN, OU, and so on).</p></td> -</tr> -<tr> -<td><code>-validity <valdays></code></td><td><p>The validity period for the -key, in days. </p><p><strong>Note:</strong> A value of 9500 or greater is recommended.</p></td> -</tr> -<tr> -<td><code>-keypass <password></code></td><td><p>The password for the key.</p> -<p>As a security precaution, do not include this option -in your command line unless you are working at a secure computer. -If not supplied, Keytool prompts you to enter the password. In this -way, your password is not stored in your shell history.</p></td> -</tr> -</table> - - -<p>Here's an example of a Keytool command that generates a private key:</p> - -<pre>$ keytool -genkey -v -keystore my-release-key.keystore --alias alias_name -keyalg RSA -validity 9500</pre> - -<p>Running the example command above, Keytool prompts you to provide -passwords for the keystore and key, and to provide the Distinguished -Name fields for your key. It then generates the keystore as a file called -<code>my-release-key.keystore</code>. The keystore and key are -protected by the passwords you entered. The keystore contains -a single key, valid for 9500 days. The alias is a name that you — -will use later, to refer to this keystore when signing your application. </p> - -<p>For more information about Keytool, see the documentation at -<a -href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security"> -http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security</a></p> - -<h3>Signing Your Application</h3> - -<p>When you are ready to actually sign your .apk for release, you can do so -using the Jarsigner tool. Make sure that you have Jarsigner available on your -machine, as described in <a href="#setup">Basic Setup</a>. Also, make sure that -the keystore containing your private key is available.</p> - -<p>To sign your application, you run Jarsigner, referencing both the -application's .apk and the keystore containing the private key with which to -sign the .apk. The table below shows the options you could use. <p> - -<table> -<tr> -<th>Jarsigner Option</th> -<th>Description</th> -</tr> -<tr> -<td><code>-keystore <keystore-name>.keystore</code></td><td>The name of -the keystore containing your private key.</td> -</tr> -<tr> -<td><code>-verbose</code></td><td>Enable verbose output.</td> -</tr> -<tr> -<td><code>-storepass <password></code></td><td><p>The password for the -keystore. </p><p>As a security precaution, do not include this option -in your command line unless you are working at a secure computer. -If not supplied, Jarsigner prompts you to enter the password. In this -way, your password is not stored in your shell history.</p></td> -</tr> -<tr> -<td><code>-keypass <password></code></td><td><p>The password for the private -key. </p><p>As a security precaution, do not include this option -in your command line unless you are working at a secure computer. -If not supplied, Jarsigner prompts you to enter the password. In this -way, your password is not stored in your shell history.</p></td> -</tr> -</table> - -<p>Here's how you would use Jarsigner to sign an application package called -<code>my_application.apk</code>, using the example keystore created above. -</p> - -<pre>$ jarsigner -verbose -keystore my-release-key.keystore -my_application.apk alias_name</pre> - -<p>Running the example command above, Jarsigner prompts you to provide -passwords for the keystore and key. It then modifies the APK -in-place, meaning the .apk is now signed. Note that you can sign an -APK multiple times with different keys.</p> - -<p>To verify that your .apk is signed, you can use a command like this:</p> - -<pre>$ jarsigner -verify my_signed.apk</pre> - -<p>If the .apk is signed properly, Jarsigner prints "jar verified". -If you want more details, you can try one of these commands:</p> - -<pre>$ jarsigner -verify -verbose my_application.apk</pre> - -<p>or</p> - -<pre>$ jarsigner -verify -verbose -certs my_application.apk</pre> - -<p>The command above, with the <code>-certs</code> option added, will show you the -"CN=" line that describes who created the key.</p> - -<p class="note">Note: if you see "CN=Android Debug", this means the .apk was -signed with the debug key generated by the Android SDK. If you intend to release -your application, you must sign it with your private key instead of the debug -key.</p> - -<p>For more information about Jarsigner, see the documentation at -<a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security"> -http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security</a></p> - -<h3 id="secure-key">Securing Your Private Key</h3> - -<p>Maintaining the security of your private key is of critical importance, both -to you and to the user. If you allow someone to use your key, or if you leave -your keystore and passwords in an unsecured location such that a third-party -could find and use them, your authoring identity and the trust of the user -are compromised. </p> - -<p>If a third party should manage to take your key without your knowledge or -permission, that person could sign and distribute applications that maliciously -replace your authentic applications or corrupt them. Such a person could also -sign and distribute applications under your identity that attack other -applications or the system itself, or corrupt or steal user data. </p> - -<p>Your reputation as a developer entity depends on your securing your private -key properly, at all times, until the key is expired. Here are some tips for -keeping your key secure: </p> - -<ul> -<li>Select strong passwords for the keystore and key.</li> -<li>When you generate your key with Keytool, <em>do not</em> supply the -<code>-storepass</code> and <code>-keypass</code> options at the command line. -If you do so, your passwords will be available in your shell history, -which any user on your computer could access.</li> -<li>Similarly, when signing your applications with Jarsigner, -<em>do not</em> supply the <code>-storepass</code> and <code>-keypass</code> -options at the command line. </li> -<li>Do not give or lend anyone your private key, and do not let unauthorized -persons know your keystore and key passwords.</li> -</ul> - -<p>In general, if you follow common-sense precautions when generating, using, -and storing your key, it will remain secure. </p> - -<h2>Expiry of the Debug Certificate</h2> - -<p>The self-signed certificate used to sign your application in debug mode (the default on -Eclipse/ADT and Ant builds) will have an expiration date of 365 days from its creation date.</p> - -<p>When the certificate expires, you will get a build error. On Ant builds, the error -looks like this:</p> - -<pre>debug: -[echo] Packaging bin/samples-debug.apk, and signing it with a debug key... -[exec] Debug Certificate expired on 8/4/08 3:43 PM</pre> - -<p>In Eclipse/ADT, you will see a similar error in the Android console.</p> - -<p>To fix this problem, simply delete the <code>debug.keystore</code> file. On Linux/Mac OSX, -the file is stored in <code>~/.android</code>. OOn Windows XP, the file is stored in <code> -C:\Documents and Settings\<user>\Local Settings\Application Data\Android</code>. -On Windows Vista, the file is stored in <code> -C:\Users\<user>\AppData\Local\Android</code>.</p> - -<p>The next time you build, the build tools will regenerate a new keystore and debug key.</p> - -<p>Note that, if your development machine is using a non-Gregorian locale, the build -tools may erroneously generate an already-expired debug certificate, so that you get an -error when trying to compile your application. For workaround information, see the -troubleshooting topic <a href="{@docRoot}kb/troubleshooting.html#signingcalendar"> -I can't compile my app because the build tools generated an expired debug -certificate</a>. </p>
\ No newline at end of file diff --git a/docs/html/guide/developing/eclipse-adt.jd b/docs/html/guide/developing/eclipse-adt.jd index 8c482ee..4f332b1 100644 --- a/docs/html/guide/developing/eclipse-adt.jd +++ b/docs/html/guide/developing/eclipse-adt.jd @@ -1,193 +1,393 @@ -page.title=In Eclipse, with ADT +page.title=Developing In Eclipse, with ADT @jd:body -<p>The Android Development Tools (ADT) plugin for Eclipse adds powerful extensions to the Eclipse integrated development environment. It allows you to create and debug Android applications easier and faster. If you use Eclipse, the ADT plugin gives you an incredible boost in developing Android applications:</p> +<div id="qv-wrapper"> + <div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#CreatingAProject">Creating an Android Project</a></li> + <li><a href="#Running">Running Your Application</a> + <ol> + <li><a href="#CreatingAnAvd">Creating an AVD</a></li> + <li><a href="#RunningAnApplication">Running an application</a></li> + </ol> + </li> + <li><a href="#RunConfig">Creating a Custom Run Configuration</a></li> + <li><a href="#Signing">Setting Up Application Signing</a></li> + <li><a href="#Tips">Eclipse Tips</a></li> + </div> +</div> + + +<p>The Android Development Tools (ADT) plugin for Eclipse adds powerful extensions to the Eclipse +integrated development environment. It allows you to create and debug Android applications easier +and faster. If you use Eclipse, the ADT plugin gives you an incredible boost in developing Android +applications:</p> <ul> - <li>It gives you access to other Android development tools from inside the Eclipse IDE. For example, ADT lets you access the many capabilities of the DDMS tool: take screenshots, manage port-forwarding, set breakpoints, and view thread and process informationd irectly from Eclipse.</li> - <li>It provides a New Project Wizard, which helps you quickly create and set up all of the basic files you'll need for a new Android application.</li> + <li>It gives you access to other Android development tools from inside the Eclipse IDE. For +example, ADT lets you access the many capabilities of the DDMS tool: take screenshots, manage +port-forwarding, set breakpoints, and view thread and process informationd irectly from Eclipse.</li> + <li>It provides a New Project Wizard, which helps you quickly create and set up all of the +basic files you'll need for a new Android application.</li> <li>It automates and simplifies the process of building your Android application.</li> - <li>It provides an Android code editor that helps you write valid XML for your Android manifest and resource files.</li> + <li>It provides an Android code editor that helps you write valid XML for your Android +manifest and resource files.</li> + <li>It will even export your project into a signed APK, which can be distributed to users.</li> </ul> -<p>To begin developing Android applications in the Eclipse IDE with ADT, you first need to download the Eclipse IDE and then download and install the ADT plugin. To do so, follow the steps given in <a href="{@docRoot}sdk/1.1_r1/installing.html#installingplugin">Installing the ADT Plugin</a>, in the installation documentation included with your SDK package. </p> - -<p>Once you've installed the ADT plugin, you begin by creating an Android -project and then set up a launch configuration. After that, you can write, run, and debug -your application. </p> +<p>To begin developing Android applications in the Eclipse IDE with ADT, you first need to +download the Eclipse IDE and then download and install the ADT plugin. To do so, follow the +steps given in <a href="{@docRoot}sdk/1.5_r1/installing.html#installingplugin">Installing +the ADT Plugin</a>.</p> -<p>The sections below provide instructions assuming that you have installed the ADT plugin -in your Eclipse environment. If you haven't installed the ADT plugin, you should do that -before using the instructions below. </p> +<p>If you are already developing applications using a version of ADT earlier than 0.9, make +sure to upgrade to the latest version before continuing. See the guide to +<a href="{@docRoot}sdk/1.5_r1/upgrading.html#UpdateAdt">Update Your Eclipse ADT Plugin</a>.</p> -<a name="creatingaproject" id="creatingaproject"></a> +<p class="note"><strong>Note:</strong> This guide assumes you are using the latest version of +the ADT plugin (0.9). While most of the information covered also applies to previous +versions, if you are using an older version, you may want to consult this document from +the set of documentation included in your SDK package (instead of the online version).</p> -<h2>Creating an Android Project</h2> -<p>The ADT plugin provides a New Project Wizard that you can use to quickly create an -Eclipse project for new or existing code. To create the project, follow these steps:</p> +<h2 id="CreatingAProject">Creating an Android Project</h2> -<a name="existingcode"></a> +<p>The ADT plugin provides a New Project Wizard that you can use to quickly create a new +Android project (or a project from existing code). To create a new project:</p> <ol> - <li>Select <strong>File</strong> > <strong>New</strong> > <strong>Project</strong></li> - <li>Select <strong>Android</strong> > <strong>Android Project</strong>, and press <strong>Next</strong></li> - <li>Select the contents for the project: - <ul> - <li>Select <strong>Create new project in workspace</strong> to start a project for new code. - <p>Enter the project name, the base package name, the name of a single Activity class to create as a stub .java file, and a name to use for your application.</p></li> - <li>Select <strong>Create project from existing source</strong> to start a project from existing code. Use this option if you want to build and run any of the sample applications included with the SDK. The sample applications are located in the samples/ directory in the SDK. - <p>Browse to the directory containing the existing source code and click OK. If the directory contains a valid Android manifest file, the ADT plugin fills in the package, activity, and application names for you.</p> - </li> - </ul> - </li> - <li>Press <strong>Finish</strong>.</li> -</ol> - -<p>The ADT plugin creates the these folders and - files for you as appropriate for the type of project:</p> - + <li>Select <strong>File</strong> > <strong>New</strong> > <strong>Project</strong>.</li> + <li>Select <strong>Android</strong> > <strong>Android Project</strong>, and click + <strong>Next</strong>.</li> + <li>Select the contents for the project: + <ul> + <li>Enter a <em>Project Name</em>. This will be the name of the folder where your + project is created.</li> + <li>Under Contents, select <strong>Create new project in workspace</strong>. + Select your project workspace location.</li> + <li>Under Target, select an Android target to be used as the project's Build Target. + The Build Target + specifies which Android platform you'd like your application built against. + <p>Unless you know that you'll be using new APIs introduced in the latest SDK, you should + select a target with the lowest platform version possible, such as Android 1.1.</p> + <p class="note"><strong>Note:</strong> You can change your the Build Target for your + project at any time: Right-click the project in the Package Explorer, select + <strong>Properties</strong>, select <strong>Android</strong> and then check + the desired Project Target.</p> + </li> + <li>Under Properties, fill in all necessary fields. <ul> - <li>src/ A - folder that includes your stub .java Activity file.</li> - <li>res/ A folder for your - resources.</li> - <li>AndroidManifest.xml The - manifest for your project. </li> + <li>Enter an <em>Application name</em>. This is the human-readable title for your + application — the name that will appear on the Android device.</li> + <li>Enter a <em>Package name</em>. This is the package namespace (following the same rules + as for packages in the Java programming language) where all your source code + will reside.</li> + <li>Select <em>Create Activity</em> (optional, of course, but common) and enter a name + for your main Activity class.</li> + <li>Enter a <em>Min SDK Version</em>. This is an integer that indicates + the minimum API Level required to properly run your application. + Entering this here automatically sets the <code>minSdkVersion</code> attribute in the + <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a> + of your Android Manifest file. If you're unsure of the appropriate API Level to use, + copy the API Level listed for the Build Target you selected in the Target tab.</li> </ul> - + </li> + </ul> + </li> + <li>Click <strong>Finish</strong>.</li> </ol> -<a name="launchconfig" id="launchconfig"></a> +<p class="note"><strong>Tip:</strong> +You can also start the New Project Wizard from the <em>New</em> icon in the toolbar.</p> + +<p>Once you complete the New Project Wizard, ADT creates the following +folders and files in your new project:</p> + <dl> + <dt><code>src/</code></dt> + <dd>Includes your stub Activity Java file. All other Java files for your application + go here.</dd> + <dt><code><em><Android Version></em>/</code> (e.g., <code>Android 1.1/</code>)</dt> + <dd>Includes the <code>android.jar</code> file that your application will build against. + This is determined by the build target that you have chosen in the <em>New Project + Wizard</em>.</dd> + <dt><code>gen/</code></dt> + <dd>This contains the Java files generated by ADT, such as your <code>R.java</code> file + and interfaces created from AIDL files.</dd> + <dt><code>assets/</code></dt> + <dd>This is empty. You can use it to store raw asset files. See + <a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>.</dd> + <dt><code>res/</code></dt> + <dd>A folder for your application resources, such as drawable files, layout files, string + values, etc. See + <a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>.</dd> + <dt><code>AndroidManifest.xml</code></dt> + <dd>The Android Manifest for your project. See + <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml + File</a>.</dd> + <dt><code>default.properties</code></dt> + <dd>This file contains project settings, such as the build target. This files is integral + to the project, as such, it should be maintained in a Source Revision Control system. + It should never be edited manually — to edit project properties, + right-click the project folder and select "Properties".</dd> + </dl> + + +<h2 id="Running">Running Your Application</h2> + +<p><em>Wait!</em> Before you can run your application on the Android Emulator, +you <strong>must</strong> create an Android Virtual Device (AVD). +An AVD is a configuration that specifies the Android platform to be used on the emulator. +You can read more about AVDs in the <a href="{@docRoot}guide/developing/index.html#avd">Developing +Overview</a>, but if you just want to get started, follow the simple guide below to create +an AVD.</p> + +<p>If you will be running your applications only on actual device hardware, you do not +need an AVD — see +<a href="{@docRoot}guide/developing/device.html">Developing On a Device</a> for information +on running your applicaiton.</p> + +<h3 id="CreatingAnAvd">Creating an AVD</h3> + +<p>To avoid some explanation that's beyond the scope of this document, here's the +basic procedure to create an AVD:</p> -<h2>Creating a Launch Configuration </h2> +<ol> + <li>Open a command-line (e.g.,"Command Prompt" application on Windows, or "Terminal" + on Mac/Linux) and navigate to your SDK package's + <code>tools/</code> directory.</li> + <li>First, you need to select a Deployment Target. To view available targets, execute: + <pre>android list targets</pre> + <p>This will output a list of available Android targets, such as:</p> +<pre> +id:1 + Name: Android 1.1 + Type: platform + API level: 2 + Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P +id:2 + Name: Android 1.5 + Type: platform + API level: 3 + Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P +</pre> + <p>Find the target that matches the Android platform upon which you'd like + to run your application. Note the integer value of the <code>id</code> — + you'll use this in the next step.</p> + </li> + <li>Create a new AVD using your selected Deployment Target. Execute: + <pre>android create avd --name <em><your_avd_name></em> --target <em><targetID></em></pre> + <li>Next, you'll be asked whether you'd like to create a custom hardware profile. + If you respond "yes," you'll be presented with a series of prompts to define various aspects of the + device hardware (leave entries blank to use default values, which are shown in brackets). Otherwise, + press return to use all default values ("no" is the default).</li> + </li> +</ol> -<p>Before you can run and debug your application in Eclipse, you must create a launch configuration for it. A launch configuration specifies the project to launch, the Activity to start, the emulator options to use, and so on. </p> +<p>That's it; your AVD is ready. In the next section, you'll see how the AVD is used +when launching your application on an emulator.</p> -<p>To create a launch configuration for the application, follow these steps as appropriate for your Eclipse version:</p> +<p>To learn more about creating and managing AVDs, please read the +<a href="{@docRoot}guide/developing/index.html#avd">Developing Overview</a> +and <a href="{@docRoot}guide/tools/android.html">android Tool</a> documentation.</p> -<ol> - <li>Open the launch configuration manager. - <ul> - <li>In Eclipse 3.3 (Europa), select <strong>Run </strong>> - <strong>Open Run Dialog... </strong>or <strong>Run </strong>> - <strong>Open Debug Dialog... </strong>as appropriate. - </li> - <li>In Eclipse 3.4 (Ganymede), select <strong>Run </strong>> - <strong>Run Configurations... </strong>or <strong>Run </strong>> - <strong>Debug Configurations... </strong>as appropriate. - </li> - </ul> - </li> - <li>In the project type list on the left, locate the <strong> Android Application</strong> item and double-click it (or right-click > <strong>New</strong>), to create a new launch configuration.</li> - <li>Enter a name for your configuration.</li> - <li>On the Android tab, browse for the project and Activity to start.</li> - <li>On the Target tab, set the desired screen and network properties, as well as any other <a href="{@docRoot}guide/developing/tools/emulator.html#startup-options">emulator startup options</a>.</li> - <li>You can set additional options on the Common tab as desired.</li> - <li>Press <strong>Apply</strong> to save the launch configuration, or press <strong>Run</strong> or <strong>Debug</strong> (as appropriate).</li> +<h3 id="RunningYourApplication">Running your application</h3> -</ol> +<p class="note"><strong>Note:</strong> Before you can run your application, be sure that +you have created an AVD with a target that satisfies your application's Build Target. +If an AVD cannot be found that meets the requirements of your Build Target, you will see +a console error telling you so and the launch will be aborted.</p> +<p>To run (or debug) your application, select <strong>Run</strong> > <strong>Run</strong> (or +<strong>Run</strong> > <strong>Debug</strong>) from the Eclipse main menu. The ADT plugin +will automatically create a default launch configuration for the project.</p> -<h2 id="sign_in_adt">Setting Up Application Signing</h2> +<p>When you choose to run or debug your application, Eclipse will perform the following:</p> -<p>As you begin developing Android applications, you should understand that all -Android applications must be digitally signed before the system will install -them on the emulator or an actual device. </p> +<ol> + <li>Compile the project (if there have been changes since the last build).</li> + <li>Create a default launch configuration (if one does not already exist for the project).</li> + <li>Install and start the application on an emulator or device (based on the Deployment Target + defined by the run configuration). + <p>By default, Android application run configurations use an "automatic target" mode for + selecting a device target. For information on how automatic target mode selects a + deployment target, see <a href="#AutoAndManualTargetModes">Automatic and manual + target modes</a> below.</p> + </li> +</ol> -<p>The ADT plugin helps you get started quickly by signing your .apk files with -a debug key, prior to installing them on the emulator. This means that you can -compile your application and install it on the emulator without having to -generate your own private key. However, please note that if you intend to -publish your application, you <em>must</em> sign the application with your own -private key, rather than the debug key generated by the SDK tools. </p> +<p>If debugging, the application will start in the "Waiting For Debugger" mode. Once the +debugger is attached, Eclipse will open the Debug perspective.</p> + +<p>To set or change the launch configuration used for your project, use the launch configuration manager. +See <a href="#launchconfig">Creating a Launch Configuration</a> for information.</p> -<p>To sign your applications, the ADT plugin requires the Keytool utility -included in the JDK. To set up your development environment for -signing, you need to make sure that Keytool is available on your -machine that the ADT plugin knows how to find it. </p> -<p>In most cases, you can tell the SDK build tools how to find Keytool by making -sure that your JAVA_HOME environment variable is set and that it references a -suitable JDK. Alternatively, you can add the JDK version of Keytool to your -PATH variable.</p> +<h2 id="RunConfig">Creating a Run Configuration</h2> -<p>If you are developing on a version of Linux that originally came with Gnu -Compiler for Java, make sure that the system is using the JDK version of -Keytool, rather than the gcj version. If keytool is already in your PATH, it -might be pointing to a symlink at /usr/bin/keytool. In this case, check the -symlink target to make sure that it points to the keytool in the JDK.</p> +<p>The run configuration specifies the project to run, the Activity +to start, the emulator options to use, and so on. When you first run a project +as an <em>Android Application</em>, ADT will automatically create a run configuration. +The default run configuration will +launch the default project Activity and use automatic target mode for device selection +(with no preferred AVD). If the default setting don't suit your project, you can +customize the launch configuration or even create a new.</p> -<p>In all cases, please read and understand <a -href="{@docRoot}guide/publishing/app-signing.html">Signing Your -Applications</a>, which provides an overview of application signing on Android -and what it means to you as an Android application developer. </p> +<p>To create or modify a launch configuration, follow these steps as appropriate +for your Eclipse version:</p> +<ol> + <li>Open the run configuration manager. + <ul> + <li>In Eclipse 3.3 (Europa), select <strong>Run</strong> > + <strong>Open Run Dialog</strong> (or <strong>Open Debug Dialog</strong>) + </li> + <li>In Eclipse 3.4 (Ganymede), select <strong>Run </strong>> + <strong>Run Configurations</strong> (or + <strong>Debug Configurations</strong>) + </li> + </ul> + </li> + <li>Expand the <strong>Android Application</strong> item and create a new + configuration or open an existing one. + <ul> + <li>To create a new configuration: + <ol> + <li>Select <strong>Android Application</strong> and click the <em>New launch configuration</em> + icon above the list (or, right-click <strong>Android Application</strong> and click + <strong>New</strong>).</li> + <li>Enter a Name for your configuration.</li> + <li>In the Android tab, browse and select the project you'd like to run with the + configuration.</li> + </ol> + <li>To open an existing configuration, select the configuration name from the list + nested below <strong>Android Application</strong>.</li> + </ul> + </li> + <li>Adjust your desired launch configuration settings. + <p>In the Target tab, consider whether you'd like to use Manual or Automatic mode + when selecting an AVD to run your application. + See the following section on <a href=#AutoAndManualModes">Automatic and manual target + modes</a>).</p> + </li> +</ol> -<a name="installingrunningdebugging" id="installingrunningdebugging"></a> -<h2>Running and Debugging an Application</h2> +<h3 id="AutoAndManualTargetModes">Automatic and manual target modes</h3> -<p>Once you've set up the project and launch configuration for your application, you can run or debug it as described below.</p> +<p>By default, a run configuration uses the <strong>automatic</strong> target mode in order to select +an AVD. In this mode, ADT will select an AVD for the application in the following manner:</p> -From the Eclipse main menu, select <strong>Run</strong> > <strong>Run</strong> or <strong>Run</strong> > <strong>Debug</strong> as appropriate, to run or debug the active launch configuration. </li> +<ol> + <li>If there's a device or emulator already running and its AVD configuration + meets the requirements of the application's build target, the application is installed + and run upon it.</li> + <li>If there's more than one device or emulator running, each of which meets the requirements + of the build target, a "device chooser" is shown to let you select which device to use.</li> + <li>If there are no devices or emulators running that meet the requirements of the build target, + ADT looks at the available AVDs. If one meets the requirements of the build target, + the AVD is used to launch a new emulator, upon which the application is installed and run.</li> + <li>If all else fails, the application will not be run and you will see a console error warning + you that there is no existing AVD that meets the build target requirements.</li> +</ol> -<p>Note that the active launch configuration is the one most recently selected in the Run configuration manager. It does not necessarily correspond to the application that is selected in the Eclipse Navigation pane (if any).</p> +<p>However, if a "preferred AVD" is selected in the run configuration, then the application +will <em>always</em> be deployed to that AVD. If it's not already running, then a new emulator +will be launched.</p> -<p>To set or change the active launch configuration, use the launch configuration manager. See <a href="#launchconfig">Creating a Launch Configuration</a> for information about how to access the launch configuration manager.</strong>.</p> +<p>If your run configuration uses <strong>manual</strong> mode, then the "device chooser" +is presented every time that your application is run, so that you can select which AVD to use.</p> -<p>Running or debugging the application triggers these actions:</p> -<ul><li>Starts the emulator, if it is not already running. </li> - <li>Compiles the project, if there have been changes since the last build, and installs the application on the emulator. </li> - <li><strong>Run</strong> starts the application. </li> - <li><strong>Debug</strong> starts the application in "Wait for debugger" mode, then opens the Debug perspective and attaches the Eclipse Java debugger to the application.</li> - </ul> +<h2 id="Signing">Signing your Applications</h2> +<p>As you begin developing Android applications, understand that all +Android applications must be digitally signed before the system will install +them on an emulator or an actual device. There are two ways to do this: +with a debug key (for immediate testing on an emulator or development device) +or with a private key (for application distribution).</p> -<h2 id="tips">Eclipse Tips </h2> - <h3>Executing arbitrary Java expressions in Eclipse<a name="arbitraryexpressions" id="arbitraryexpressions"></a></h3> - <p>You can execute arbitrary code when paused at a breakpoint in Eclipse. For example, - when in a function with a String argument called "zip", you can get - information about packages and call class methods. You can also invoke arbitrary - static methods: for example, entering <code>android.os.Debug.startMethodTracing()</code> will - start dmTrace. </p> - <p>Open a code execution window, select <strong>Window</strong>><strong>Show - View</strong>><strong>Display</strong> from the main menu to open the - Display window, a simple text editor. Type your expression, highlight the - text, and click the 'J' icon (or CTRL + SHIFT + D) to run your - code. The code runs in the context of the selected thread, which must be - stopped at a breakpoint or single-step point. (If you suspend the thread - manually, you have to single-step once; this doesn't work if the thread is - in Object.wait().)</p> - <p>If you are currently paused on a breakpoint, you can simply highlight and execute - a piece of source code by pressing CTRL + SHIFT + D. </p> - <p>You can highlight a block of text within the same scope by pressing ALT +SHIFT - + UP ARROW to select larger and larger enclosing blocks, or DOWN ARROW to select - smaller blocks. </p> - <p>Here are a few sample inputs and responses in Eclipse using the Display window.</p> - <table width="100%" border="1"> - <tr> - <th scope="col">Input</th> - <th scope="col">Response</th> - </tr> - <tr> - <td><code>zip</code></td> - <td><code>(java.lang.String) /work/device/out/linux-x86-debug/android/app/android_sdk.zip</code></td> - </tr> - <tr> - <td><code>zip.endsWith(".zip")</code></td> - <td><code>(boolean) true</code></td> - </tr> - <tr> - <td><code>zip.endsWith(".jar")</code></td> - <td><code>(boolean) false</code></td> - </tr> - </table> - <p>You can also execute arbitrary code when not debugging by using a scrapbook page. - Search the Eclipse documentation for "scrapbook".</p> - - <h3>Running DDMS Manually</h3> - - <p>Although the recommended way to debug is to use the ADT plugin, you can manually run DDMS and configure Eclipse to debug on port 8700. (<strong>Note: </strong>Be sure that you have first started <a href="{@docRoot}guide/developing/tools/ddms.html">DDMS</a>). </p> +<p>The ADT plugin helps you get started quickly by signing your .apk files with +a debug key, prior to installing them on an emulator or development device. This means that you can +quickly run your application from Eclipse without having to +generate your own private key. No specific action on your part is needed, +provided ADT has access to Keytool.However, please note that if you intend +to publish your application, you <strong>must</strong> sign the application with your +own private key, rather than the debug key generated by the SDK tools.</p> + +<p>Please read <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your +Applications</a>, which provides a thorough guide to application signing on Android +and what it means to you as an Android application developer. The document also includes +a guide to exporting and signing your application with the ADT's Export Wizard.</p> + + +<h2 id="Tips">Eclipse Tips </h2> + +<h3 id="arbitraryexpressions">Executing arbitrary Java expressions in Eclipse</h3> + +<p>You can execute arbitrary code when paused at a breakpoint in Eclipse. For example, + when in a function with a String argument called "zip", you can get + information about packages and call class methods. You can also invoke arbitrary + static methods: for example, entering <code>android.os.Debug.startMethodTracing()</code> will + start dmTrace. </p> +<p>Open a code execution window, select <strong>Window</strong>><strong>Show + View</strong>><strong>Display</strong> from the main menu to open the + Display window, a simple text editor. Type your expression, highlight the + text, and click the 'J' icon (or CTRL + SHIFT + D) to run your + code. The code runs in the context of the selected thread, which must be + stopped at a breakpoint or single-step point. (If you suspend the thread + manually, you have to single-step once; this doesn't work if the thread is + in Object.wait().)</p> +<p>If you are currently paused on a breakpoint, you can simply highlight and execute + a piece of source code by pressing CTRL + SHIFT + D. </p> +<p>You can highlight a block of text within the same scope by pressing ALT +SHIFT + + UP ARROW to select larger and larger enclosing blocks, or DOWN ARROW to select + smaller blocks. </p> +<p>Here are a few sample inputs and responses in Eclipse using the Display window.</p> + +<table width="100%" border="1"> + <tr> + <th scope="col">Input</th> + <th scope="col">Response</th> + </tr> + <tr> + <td><code>zip</code></td> + <td><code>(java.lang.String) + /work/device/out/linux-x86-debug/android/app/android_sdk.zip</code></td> + </tr> + <tr> + <td><code>zip.endsWith(".zip")</code></td> + <td><code>(boolean) true</code></td> + </tr> + <tr> + <td><code>zip.endsWith(".jar")</code></td> + <td><code>(boolean) false</code></td> + </tr> +</table> +<p>You can also execute arbitrary code when not debugging by using a scrapbook page. + Search the Eclipse documentation for "scrapbook".</p> + + +<h3>Running DDMS Manually</h3> + +<p>Although the recommended way to debug is to use the ADT plugin, you can manually run +DDMS and configure Eclipse to debug on port 8700. (<strong>Note: </strong>Be sure that you +have first started <a href="{@docRoot}guide/developing/tools/ddms.html">DDMS</a>). </p> + + +<!-- TODO: clean this up and expand it to cover more wizards and features +<h3>ADT Wizards</h3> + +<p>Notice that the "New Android Project" wizard has been expanded to use the multi-platform +capabilities of the new SDK.</p> + +<p>There is now a "New XML File" wizard that lets you create skeleton XML resource +files for your Android projects. This makes it easier to create a new layout, a new menu, a +new strings file, etc.</p> + +<p>Both wizards are available via <strong>File > New</strong> and new icons in the main +Eclipse toolbar (located to the left of the Debug and Run icons). +If you do not see the new icons, you may need to select <strong>Window > Reset +Perspective</strong> from the Java perspective.</p> +--> diff --git a/docs/html/guide/developing/other-ide.jd b/docs/html/guide/developing/other-ide.jd index 7bcb509..5db4f8d 100644 --- a/docs/html/guide/developing/other-ide.jd +++ b/docs/html/guide/developing/other-ide.jd @@ -1,167 +1,408 @@ -page.title=In Other IDEs +page.title=Developing In Other IDEs @jd:body +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#CreatingAProject">Creating an Android Project</a></li> + <li><a href="#Signing">Preparing to Sign Your Application</a></li> + <li><a href="#Building">Building Your Application</a> + <ol> + <li><a href="#DebugMode">Building in debug mode</a></li> + <li><a href="#ReleaseMode">Building in release mode</a></li> + </ol> + </li> + <li><a href="#Running">Running Your Application</a></li> + <li><a href="#AttachingADebugger">Attaching a Debugger to Your Application</a></li> + </ol> + + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/developing/tools/android.html">android Tool</a></li> + <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></li> + <li><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a></li> + </ol> +</div> +</div> + <p>The recommended way to develop an Android application is to use - <a href="{@docRoot}guide/developing/eclipse-adt.html">Eclipse with the Android - Development Tools (ADT) plugin</a>, provided in the SDK. The ADT plugin - provides editing, building,and debugging functionality integrated right into the IDE. </p> +<a href="{@docRoot}guide/developing/eclipse-adt.html">Eclipse with the ADT plugin</a>. +The ADT plugin provides editing, building, debugging, and .apk packaging and signing functionality +integrated right into the IDE.</p> -<p>However, if you'd rather develop your application in another IDE, such as IntelliJ, - or use Eclipse without the ADT plugin, you can do that instead. The SDK - provides the tools you need to set up, build, and debug your application. - </p> +<p>However, if you'd rather develop your application in another IDE, such as IntelliJ, +or in a basic editor, such as Emacs, you can do that instead. The SDK +includes all the tools you need to set up an Android project, build it, debug it and then +package it for distribution. This document is your guide to using these tools.</p> -<h2>Creating an Android Project </h2> +<h2 id="EssentialTools">Essential Tools</h2> -<p>The Android SDK includes <code>activityCreator</code>, a program that generates a number of stub files for your project, as well as a build file. You can use the program to create an Android project for new code or from existing code, such as the sample applications included in the SDK. For Linux and Mac, the SDK provides <code>activitycreator</code> and for Windows, <code>activityCreator.bat</code>, a batch script. Regardless of platform, you can use <code>activitycreator</code> in the same way. </p> +<p>When developing in IDEs or editors other than Eclipse, you'll require +familiarity with the following Android SDK tools:</p> -<p>To run <code>activityCreator</code> and create an Android project, follow these steps:</p> +<dl> + <dt><a href="{@docRoot}guide/developing/tools/android.html">android</a></dt> + <dd>To create/update Android projects and to create/move/delete AVDs.</dd> + <dt><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></dt> + <dd>To run your Android applications on an emulated Android platform.</dd> + <dt><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a></dt> + <dd>To interface with your emulator or connected device (install apps, + shell the device, issue commands, etc.). + </dd> +</dl> + +<p>In addition to the above tools, included with the SDK, you'll use the following +open source and third-party tools:</p> + +<dl> + <dt>Ant</dt> + <dd>To compile and build your Android project into an installable .apk file.</dd> + <dt>Keytool</dt> + <dd>To generate a keystore and private key, used to sign your .apk file.</dd> + <dt>Jarsigner (or similar signing tool)</dt> + <dd>To sign your .apk file with a private key generated by keytool.</dd> +</dl> + +<p>In the topics that follow, you'll be introduced to each of these tools as necessary. +For more advanced operations, please read the respective documentation for each tool.</p> + + +<h2 id="CreatingAProject">Creating an Android Project</h2> + +<p>To create an Android project, you must use the <code>android</code> tool. When you create +a new project with <code>android</code>, it will generate a project directory +with some default application files, stub files, configuration files and a build file.</p> -<ol> - <li> In the command line, change to the <code>tools/</code> directory of the SDK and create a new directory for your project files. If you are creating a project from existing code, change to the root folder of your application instead. </li> - <li><p>Run <code>activityCreator</code>. In the command, you must specify a fully-qualified class name as an argument. If you are creating a project for new code, the class represents the name of a stub class that the script will create. If you are creating a project from existing code, you must specify the name of one Activity class in the package. Command options for the script include: +<h3 id="CreatingANewProject">Creating a new Project</h3> + +<p>If you're starting a new project, use the <code>android create project</code> +command to generate all the necessary files and folders.</p> + +<p>To create a new Android project, open a command-line, +navigate to the <code>tools/</code> directory of your SDK and run:</p> +<pre> +android create project \ +--target <em><targetID></em> \ +--path <em>/path/to/your/project</em> \ +--activity <em><your_activity_name></em> \ +--package <em><your_package_namespace></em> +</pre> + <ul> - <li><code>--out <folder></code> which sets the output directory. By default, the output directory is the current directory. If you created a new directory for your project files, use this option to point to it. </li> - <li><code>--ide intellij</code>, which generates IntelliJ IDEA project files in the newly created project</li> + <li><code>target</code> is the "build target" for your application. It corresponds + to an Android platform library (including any add-ons, such as Google APIs) that you would like to + build your project against. To see a list of available targets and their corresponding IDs, + execute: <code>android list targets</code>.</li> + <li><code>path</code> is the location of your project directory. If the directory does not exist, + it will be created for you.</li> + <li><code>activity</code> is the name for your {@link android.app.Activity} class. This class file + will be created for you inside + <code><em><path_to_your_project></em>/src/<em><your_package_namespace_path></em>/</code>.</li> + <li><code>package</code> is the package namespace for your project, following the same rules as for + packages in the Java programming language.</li> </ul> -</li> -</ol> -<p>Here's an example:</p> +<p>Here's an example:</p> <pre> -~/android_linux_sdk/tools $ ./activityCreator.py --out myproject your.package.name.ActivityName -package: your.package.name -out_dir: myproject -activity_name: ActivityName -~/android_linux_sdk/tools $ </pre> +android create project \ +--target 1 \ +--path ./myProject \ +--activity MyActivity \ +--package com.example.myproject +</pre> -<p>The <code>activityCreator</code> script generates the following files and directories (but will not overwrite existing ones):</p> +<p>The tool generates the following files and directories:</p> <ul> - <li><code>AndroidManifest.xml</code> The application manifest file, synced to the specified Activity class for the project.</li> - <li><code>build.xml</code> An <code>Ant</code> file that you can use to build/package the application.</li> - <li><code>src<em>/your/package/name/ActivityName</em>.java</code> The Activity class you specified on input.</li> - <li><code><em>your_activity</em>.iml, <em>your_activity</em>.ipr, - <em>your_activity</em>.iws </code> [<em>only - with the <code>-ide intelliJ</code> flag</em>] intelliJ project - files. </li> - <li><code>res/</code> A directory to hold resources. </li> - <li><code>src/</code> The source directory. - <li><code>bin/</code> The output directory for the build script.</li> + <li><code>AndroidManifest.xml</code> - The application manifest file, + synced to the specified Activity class for the project.</li> + <li><code>build.xml</code> - Build file for Ant.</li> + <li><code>default.properties</code> - Properties for the build system. <em>Do not modify + this file</em>.</li> + <li><code>build.properties</code> - Customizable properties for the build system. You can edit this + file to overried default build settings used by Ant.</li> + <li><code>src<em>/your/package/namespace/ActivityName</em>.java</code> - The Activity class + you specified during project creation.</li> + <li><code>bin/</code> - Output directory for the build script.</li> + <li><code>gen/</code> - Holds <code>Ant</code>-generated files, such as <code>R.java</code>. </li> + <li><code>libs/</code> - Holds private libraries.</li> + <li><code>res/</code> - Holds project resources.</li> + <li><code>src/</code> - Holds source code.</li> + <li><code>tests/</code> - Holds a duplicate of all-of-the-above, for testing purposes.</li> </ul> -<p>You can now move your folder wherever you want for development, but keep in mind - that you'll have to use the <a href="{@docRoot}guide/developing/tools/adb.html">adb</a> program in the <code>tools/</code> folder to - send files to the emulator, so you'll need access between your solution and - the <code>tools/</code> folder. </p> - -<p>Also, you should refrain from moving the - location of the SDK directory, since this will break the build scripts (they - will need to be manually updated to reflect the new SDK location before they will - work again).</p> -<a name="buidingwithant"></a> -<h2 id="antbuild">Building the Application with Ant</h2> -<p>Use the Ant <code>build.xml</code> file generated by - <code>activityCreator</code> to build your application.</p> -<ol> - <li>If you don't have it, you can obtain Ant from the - <a href="http://ant.apache.org/">Apache Ant home page</a>. Install it and make - sure it is on your executable path. </li> - <li>Before calling Ant, you need to declare the JAVA_HOME environment variable to specify the path to where the JDK is installed. - <p class="note"><strong>Note:</strong> When installing JDK on Windows, the default is to install in the "Program Files" directory. This location will cause <code>ant</code> to fail, because of the space. To fix the problem, you can specify the JAVA_HOME variable like this: <code>set JAVA_HOME=c:\Prora~1\Java\<jdkdir></code>. The easiest solution, however, is to install JDK in a non-space directory, for example: <code>c:\java\jdk1.6.0_02</code>. </p> - </li> - - - <li>If you have not done so already, follow the instructions for Creating a - New Project above to set up the project.</li> - <li>You can now run the Ant build file by simply typing ant in the same folder - as the build.xml file for your project. Each time you change - a source file or resource, you should run ant again and it will package up the - latest version of the application for you to deploy.</li> -</ol> +<p>Once you've created your project, you're ready to begin development. +You can move your project folder wherever you want for development, but keep in mind +that you must use the <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> +(adb) — located in the SDK <code>tools/</code> directory — to send your application +to the emulator (discussed later). So you need access between your project solution and +the <code>tools/</code> folder.</p> + +<p class="warning"><strong>Note:</strong> You should refrain from moving the +location of the SDK directory, because this will break the build scripts. (They +will need to be manually updated to reflect the new SDK location before they will +work again.)</p> + -<h2 id="sign_in_other">Setting Up Application Signing</h2> +<h3 id="UpdatingAProject">Updating a project</h3> -<p>As you begin developing Android applications, you should understand that all +<p>If you're upgrading a project from an older version of the Android SDK or want to create +a new project from existing code, use the +<code>android update project</code> command to update the project to the new development +environment. You can also use this command to revise the build target of an existing project +(with the <code>--target</code> option). The <code>android</code> tool will generate any files and +folders (listed in the previous section) that are either missing or need to be updated, +as needed for the Android project.</p> + +<p>To update an existing Android project, open a command-line +and navigate to the <code>tools/</code> directory of your SDK. Now run:</p> +<pre> +android update project --target <em><targetID></em> --path <em>path/to/your/project/</em> +</pre> + +<ul> + <li><code>target</code> is the "build target" for your application. It corresponds to + an Android platform library (including any add-ons, such as Google APIs) that you would + like to build your project against. To see a list of available targets and their corresponding IDs, + execute: <code>android list targets</code>.</li> + <li><code>path</code> is the location of your project directory.</li> +</ul> + +<p>Here's an example:</p> +<pre> +android update project --target 2 --path ./myProject +</pre> + + +<h2 id="Signing">Preparing to Sign Your Application</h2> + +<p>As you begin developing Android applications, understand that all Android applications must be digitally signed before the system will install -them on the emulator or an actual device. </p> +them on an emulator or device. There are two ways to do this: +with a <em>debug key</em> (for immediate testing on an emulator or development device) +or with a <em>private key</em> (for application distribution).</p> -<p>The Android build tools help you get started quickly by signing your .apk -files with a debug key, prior to installing them on the emulator. This means +<p>The Android build tools help you get started by automatically signing your .apk +files with a debug key at build time. This means that you can compile your application and install it on the emulator without having to generate your own private key. However, please note that if you intend -to publish your application, you <em>must</em> sign the application with your +to publish your application, you <strong>must</strong> sign the application with your own private key, rather than the debug key generated by the SDK tools. </p> -<p>To sign your applications, the ADT plugin requires the Keytool utility -included in the JDK. To set up your development environment for -signing, all you need to do is make sure that Keytool is available on your -machine that the build tools know how to find it. </p> - -<p>In most cases, you can tell the SDK build tools how to find Keytool by making -sure that -your JAVA_HOME environment variable is set and that it references a suitable -JDK. Alternatively, -you can add the JDK version of Keytool to your PATH variable.</p> - -<p>If you are developing on a version of Linux that originally came with Gnu -Compiler for Java, -make sure that the system is using the JDK version of Keytool, rather than the -gcj version. -If keytool is already in your PATH, it might be pointing to a symlink at -/usr/bin/keytool. -In this case, check the symlink target to make sure that it points to the -keytool in the JDK.</p> - -<p>In all cases, please read and understand <a -href="{@docRoot}guide/publishing/app-signing.html">Signing Your -Applications</a>, which provides an overview of application signing on Android -and what it means to you as an Android application developer. </p> - - -<h2>Running an Android Application</h2> -<p>To run a compiled - application, you will upload the .apk file to the <code>/data/app/ </code>directory - in the emulator using the <a href="{@docRoot}guide/developing/tools/adb.html">adb</a> tool as described here:</p> +<p>Please read <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your +Applications</a>, which provides a thorough guide to application signing on Android +and what it means to you as an Android application developer.</p> + + + +<h2 id="Building">Building Your Application</h2> + +<p>There are two ways to build your application: one for testing/debugging your application +— <em>debug mode</em> — and one for building your final package for release — +<em>release mode</em>. As described in the previous +section, your application must be signed before it can be installed on an emulator +or device.</p> + +<p>Whether you're building in debug mode or release mode, you +need to use the Ant tool to compile and build your project. This will create the .apk file +that is installed onto the emulator or device. When you build in debug mode, the .apk +file is automatically signed by the SDK tools with a debug key, so it's instantly ready for installation +(but only onto an emulator or attached development device). +When you build in release mode, the .apk file is <em>unsigned</em>, so you must manually +sign it with your own private key, using Keytool and Jarsigner.</p> + +<p>It's important that you read and understand +<a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>, particularly +once you're ready to release your application and share it with end-users. That document describes +the procedure for generating a private key and then using it to sign your .apk file. +If you're just getting started, however, +you can quickly run your applications on an emulator or your own development device by building in +debug mode.</p> + +<p>If you don't have Ant, you can obtain it from the +<a href="http://ant.apache.org/">Apache Ant home page</a>. Install it and make +sure it is in your executable PATH. Before calling Ant, you need to declare the JAVA_HOME +environment variable to specify the path to where the JDK is installed.</p> + +<p class="note"><strong>Note:</strong> When installing JDK on Windows, the default is to install +in the "Program Files" directory. This location will cause <code>ant</code> to fail, because of +the space. To fix the problem, you can specify the JAVA_HOME variable like this: +<code>set JAVA_HOME=c:\Prora~1\Java\<jdkdir></code>. The easiest solution, however, is to +install JDK in a non-space directory, for example: <code>c:\java\jdk1.6.0_02</code>.</p> + + +<h3 id="DebugMode">Building in debug mode</h3> + +<p>For immediate application testing and debugging, you can build your application +in debug mode and immediately install it on an emulator. In debug mode, the build tools automatically +sign your application with a debug key. However, you can (and should) also test your +application in release mode. Debug mode simply allows you to run your application without +manually signing the application.</p> + +<p>To build in debug mode:</p> + +<ol> + <li>Open a command-line and navigate to the root of your project directory.</li> + <li>Use Ant to compile your project in debug mode: + <pre>ant debug</pre> + <p>This creates your Android application .apk file inside the project <code>bin/</code> + directory, named <code><em><your_DefaultActivity_name></em>-debug.apk</code>. The file + is already signed with the debug key.</p> + </li> +</ol> + +<p>Each time you change a source file or resource, you must run Ant +again in order to package up the latest version of the application.</p> + +<p>To install and run your application on an emulator, see the following section +about <a href="#Running">Running Your Application</a>.</p> + + +<h3 id="ReleaseMode">Building in release mode</h3> + +<p>When you're ready to release and distribute your application to end-users, you must build +your application in release mode. Once you have built in release mode, it's a good idea to perform +additional testing and debugging with the final .apk.</p> + +<p>To build in release mode:</p> + +<ol> + <li>Open a command-line and navigate to the root of your project directory.</li> + <li>Use Ant to compile your project in release mode: + <pre>ant release</pre> + <p>This creates your Android application .apk file inside the project <code>bin/</code> + directory, named <code><em><your_DefaultActivity_name></em>.apk</code>.</p> + <p class="note"><strong>Note:</strong> The .apk file is <em>unsigned</em> at this point. + You can't install it on an emulator or device until you sign it with your private key.</p> + </li> +</ol> + +<p>Because release mode builds your application unsigned, your next step is to sign +it with your private key, in order to distribute it to end-users. To complete this procedure, +read <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>.</p> + +<p>Once you have signed your application with a private key, you can install it on an +emulator or device as discussed in the following section about +<a href="#Running">Running Your Application</a>. +You can also try installing it onto a device from a web server. +Simply upload the signed APK to a web site, then load the .apk URL in your Android web browser to +download the application and begin installation. +(On your device, be sure you have enabled <em>Settings > Applications > Unknown sources</em>.)</p> + + +<h2 id="Running">Running Your Application</h2> + +<p>Unless you'll be running your application on device hardware, +you need to launch an emulator upon which you will install your application. +An instance of the Android emulator runs a specific Android platform with specific device configuration +settings. The platform and configuration is defined with an Android Virtual Device (AVD). +So before you can launch your emulator, you must define an AVD.</p> + +<p>If you'll be running your application on device hardware, please read about +<a href="{@docRoot}guide/developing/device.html">Developing On a Device</a> instead.</p> + <ol> - <li>Start the emulator (run <code><em><your_sdk_dir></em>/tools/emulator</code> from the command line)</li> - <li>On the emulator, navigate to the home screen (it is best not to have that - application running when you reinstall it on the emulator; press the <strong>Home</strong> key - to navigate away from that application).</li> - <li>Run <code>adb install <em>myproject</em>/bin/<<em>appname</em>>.apk</code> to upload - the executable. So, for example, to install the Lunar Lander sample, navigate - in the command line to <code><em><your_sdk_dir></em>/sample/LunarLander</code> and type <code>../../tools/adb install bin/LunarLander.apk</code></li> - <li>In the emulator, open the list of available applications, and scroll down to - select and start your application. </li> + <li><strong>Create an AVD</strong> + <ol> + <li>Open a command-line and navigate to your SDK package's + <code>tools/</code> directory.</li> + <li>First, you need to select a "deployment target." To view available targets, execute: + <pre>android list targets</pre> + <p>This will output a list of available Android targets, such as:</p> +<pre> +id:1 + Name: Android 1.1 + Type: platform + API level: 2 + Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P +id:2 + Name: Android 1.5 + Type: platform + API level: 3 + Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P +</pre> + <p>Find the target that matches the Android platform upon which you'd like + to run your application. Note the integer value of the <code>id</code> — + you'll use this in the next step.</p> + </li> + <li>Create a new AVD using your selected deployment target: + <pre>android create avd --name <em><your_avd_name></em> --target <em><targetID></em></pre> + <li>Next, you'll be asked whether you'd like to create a custom hardware profile. + If you respond "yes," you'll be presented with a series of prompts to define various aspects of the + device hardware (leave entries blank to use default values, which are shown in brackets). Otherwise, + press return to use all default values ("no" is the default).</li> + </li> + </ol> + </li> + + <li><strong>Launch an emulator</strong></li> + <p>From your SDK's <code>tools/</code> directory, launch an emulator + using an existing AVD (created above): + <pre>emulator -avd <em><your_avd_name></em></pre> + <p>An instance of the emulator will now launch, running the target and configuration + defined by your AVD.</p> + </li> + + <li><strong>Install your application</strong> + <p>From your SDK's <code>tools/</code> directory, install the .apk on the emulator: + <pre>adb install <em>/path/to/your/application</em>.apk</pre> + <p>If there is more than one emulator running, you must specify the emulator upon which to install + the application, by its serial number, with the <code>-s</code> option. For example:</p> + <pre>adb -s emulator-5554 install /my/project/path/myapp.apk</pre> + </li> + <li><strong>Open your application</strong> + <p>In the emulator, open the list of available applications to find + and open your application.</p> + </li> </ol> -<p class="note"><strong>Note:</strong> When you install an Activity for the - first time, you might have to restart the emulator before it shows up in the - application launcher, or other applications can call it. This is because - the package manager usually only examines manifests completely on emulator - startup.</p> -<h2>Attaching a Debugger to Your Application</h2> +<p>If you don't see your application on the emulator. Try restarting the emulator +(with the same AVD). Sometimes when you install an Activity for the +first time, it won't show up in the application launcher or be accessible by other +applications. This is because the package manager usually examines manifests +completely only on emulator startup.</p> + +<p class="note"><strong>Tip:</strong> If you have only one emulator running, +you can build your application and install it on the emulator in one simple step. +Navigate to the root of your project directory and use Ant to compile the project +with <em>install mode</em>: +<code>ant install</code>. This will build your application, sign it with the debug key, +and install it on the currently running emulator. +If there is more than one emulator currently running +when using the <code>install</code> command, it will fail — it can't select between the +multiple emulators.</p> + +<p>For more information on the tools used above, please see the following documents:</p> +<ul> + <li><a href="{@docRoot}guide/developing/tools/android.html">android Tool</a></li> + <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></li> + <li><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (ADB)</li> +</ul> + + +<h2 id="AttachingADebugger">Attaching a Debugger to Your Application</h2> + <p>This section describes how to display debug information on the screen (such as CPU usage), as well as how to hook up your IDE to debug running applications on the emulator. </p> <p>Attaching a debugger is automated using the Eclipse plugin, but you can configure other IDEs to listen on a debugging port to receive debugging - information.</p> + information:</p> <ol> - <li><strong>Start the <a href="{@docRoot}guide/developing/tools/ddms.html">Dalvik Debug Monitor Server (DDMS) - tool </a>, </strong> which + <li><strong>Start the <a href="{@docRoot}guide/developing/tools/ddms.html">Dalvik Debug Monitor + Server (DDMS)</a> tool, </strong> which acts as a port forwarding service between your IDE and the emulator.</li> <li><strong>Set optional debugging configurations on - your emulator</strong>, such as blocking application startup for an activity + your emulator</strong>, such as blocking application startup for an Activity until a debugger is attached. Note that many of these debugging options can be used without DDMS, such as displaying CPU usage or screen refresh rate on the emulator.</li> - <li><strong>Configure your IDE to attach to port 8700 for debugging.</strong> We - include information on <a href="{@docRoot}guide/developing/debug-tasks.html#ide-debug-port"> - how to set up Eclipse to debug your project</a>. </li> - + <li><strong>Configure your IDE to attach to port 8700 for debugging.</strong> Read + about <a href="{@docRoot}guide/developing/debug-tasks.html#ide-debug-port"> + Configuring Your IDE to Attach to the Debugging Port</a>. </li> </ol> diff --git a/docs/html/guide/developing/tools/avd.jd b/docs/html/guide/developing/tools/avd.jd index 7ba7968..1e13ace 100644 --- a/docs/html/guide/developing/tools/avd.jd +++ b/docs/html/guide/developing/tools/avd.jd @@ -21,13 +21,12 @@ page.title=Android Virtual Devices <li><a href="#createavd">Creating the AVD</a></li> <li><a href="#hardwareopts">Setting hardware emulation options</a></li> <li><a href="#location">Default location of the AVD files</a></li> - <li><a href="#createavdopts">Command-line options, create avd</a></li> </ol> </li> <li><a href="#managing">Managing AVDs</a> <ol> <li><a href="#moving">Moving an AVD</a></li> - <li><a href="#updating">Deleting an AVD</a></li> + <li><a href="#updating">Updating an AVD</a></li> <li><a href="#deleting">Deleting an AVD</a></li> </ol> </li> @@ -35,7 +34,8 @@ page.title=Android Virtual Devices </ol> <h2>See Also</h2> <ol> - <li>Android <a href="{@docRoot}guide/developing/tools/emulator.html">Emulator</a></li> + <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android + Emulator</a></li> </ol> </div> </div> @@ -366,6 +366,10 @@ the <code>-p</code> option to place the AVD directory in another location. The AVD's .ini file remains in the .android directory on the network drive, regardless of the location of the AVD directory. </p> +<h2 id="managing">Managing AVDs</h2> + +<p>The sections below provide more information about how to manage AVDs once you've created them. </p> + <h3 id="moving">Moving an AVD</h3> <p>If you want to move or rename an AVD, you can do so using this command:</p> @@ -455,7 +459,7 @@ files.</td> </tr> <tr> <td><code>-s <name></code> or <br> - <code>-s <dimensions></code> </td> + <code>-s <width>-<height></code> </td> <td>The skin to use for this AVD, identified by name or dimensions.</td> <td>The android tool scans for a matching skin by name or dimension in the <code>skins/</code> directory of the target referenced in the <code>-t diff --git a/docs/html/guide/topics/location/geo/mapkey.jd b/docs/html/guide/topics/location/geo/mapkey.jd deleted file mode 100644 index 9aa824c..0000000 --- a/docs/html/guide/topics/location/geo/mapkey.jd +++ /dev/null @@ -1,210 +0,0 @@ -page.title=Obtaining a Maps API Key -@jd:body - -<div class="sidebox"><p>To register for a Maps API Key, read this document and then go to the <a href="http://code.google.com/android/maps-api-signup.html">Android Maps API Key Signup</a> page.</p> - -</div> - -<p>com.google.android.maps.MapView is a very useful class that lets you easily integrate Google Maps into your application. It provides built-in map downloading, rendering, and caching of Maps tiles, as well as a variety of display options and controls. It provides a wrapper around the Google Maps API that lets your application request and manipulate Google Maps data through class methods, and it lets you work with Maps data as you would other types of Views. </p> - -<p>Because MapView gives you access to Google Maps data, you need to register with the Google Maps service and agree to the applicable Terms of Service before your MapView will be able to obtain data from Google Maps. This will apply whether you are developing your application on the emulator or preparing your application for deployment to mobile devices. </p> - -<p>Registering for a Maps API Key is simple, free, and has two parts: </p> - -<ol> -<li>Registering the MD5 fingerprint of the certificate that you will use to sign your application. The Maps registration service then provides you a Maps API Key that is associated with your application's signer certificate. </li> -<li>Adding a reference to the Maps API Key in each MapView, whether declared in XML or instantiated directly from code. You can use the same Maps API Key for any MapView in any Android application, provided that the application is signed with the certificate whose fingerprint you registered with the service. </li> -</ol> - -<p>During registration, you also need to agree to the Maps API Terms of Service, which describe how your application can use the Maps data. In general, the terms of service are permissive and place few restrictions on how you can use the data. For example, the terms allow you to build "friend finder" type applications. </p> - -<p>The sections below describe how to obtain your Maps API Key and how to reference it from your MapView elements. </p> - -<ul> -<li><a href="#overview">Overview</a></li> -<li><a href="#getfingerprint">Getting the MD5 Fingerprint of Your Signing Certificate</a></li> -<li><a href="#getdebugfingerprint">Getting the MD5 Fingerprint of the SDK Debug Certificate</a></li> -<li><a href="#registering">Registering the Certificate Fingerprint with the Google Maps Service</a></li> -<li><a href="#addingkey">Adding the Maps API Key to your Application</a></li> -<li><a href="#finalsteps">Final Steps to Enable MapView Elements</a></li> -</ul> - -<h2 id="overview">Overview</h2> - -<p>MapView objects are views that display Maps tiles downloaded from the Google Maps service. To ensure that applications use Maps data in an appropriate manner, the Google Maps service requires application developers to register with the service, agreeing to the Terms of Service and supplying an MD5 fingerprint of the certificate(s) that they will use to sign applications. For each registered certificate fingerprint, the service then provides the developer with a Maps API Key — an alphanumeric string that uniquely identifies the certificate and developer registered with the service. </p> - -<p>The Google Maps service also requires that each MapView identify itself to the service using a Maps API Key. Before providing Maps tiles to a MapView, the service checks the Maps API Key supplied by the MapView to ensure that it:</p> -<ul> -<li>References a certificate/developer registered with the service, and </li> -<li>References a certificate that matches the certificate with which the application (containing the MapView) was signed. </li> -</ul> - -<p>Unless both conditions are met, the service does not provide Maps tiles to the MapView. </p> - -<p>Each MapView object in your application must reference a Maps API Key. Since the Key is associated with a certificate, all Mapview elements in an application should reference the same Key. Going a step further, all MapView elements in all applications that you sign with the same certificate should reference the same Key. </p> - -<p>On the other hand, you can register for multiple Maps API Keys, each being associated with a specific certificate. You would want to do this if, for example, you were developing several independent applications that you will sign using different certificates. In this case, note that all MapView elements in a given application can reference the same Maps API Key, but <em>must</em> reference the Key that is associated with the certificate used to sign the application. </p> - -<p>Because MapView elements must refer to a Maps API Key, you need to register your certificate and receive a Key before you can make use of MapView elements in your application. To make it easier for you to get started using MapView elements, you are welcome to register the debug certificate generated by the SDK tools and receive a temporary Maps API Key. The details of how to do that are given below. </p> - -<p>When you are preparing to release your application, however, note that you <em>must</em> sign your application with a suitable cryptographic key, rather than the SDK debug key. That means that you will also need to register your application's release certificate with the Google Maps service. After you've done so, you will receive a new Maps API Key that is uniquely associated with your release certificate. To enable the MapView elements in your application to work after release, you must remember to change the Maps API Key for all MapViews in your application so that they refer to the Key associated with your release certificate (rather than your debug certificate). </p> - -<p>To summarize, the important points to understand about MapViews and the Maps API Key are: </p> - -<ul> -<li>To display Maps data in a MapView, you need to register for a Maps API Key</li> -<li>Each Maps API Key is uniquely associated with a specific certificate, based on an MD5 fingerprint of the certificate </li> -<li>Each MapView must reference a Maps API Key, and the Key referenced must be registered to the certificate used to sign the application</li> -<li>All MapView elements in an application can reference the same Maps API Key</li> -<li>You can register multiple certificates under your developer identity</li> -<li>You can get a temporary Maps API Key based on your debug certificate, but before you publish your application, you must register for a new Key based on your release certificate and update references in your MapViews accordingly</li> -</ul> - -<h2 id="getfingerprint">Getting the MD5 Fingerprint of Your Signing Certificate</h2> - -<div class="sidebox"> -For more information about using Keytool and Jarsigner to sign your application, see <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>. -</div> - -<p>To register for a Maps API Key, you need to provide an MD5 fingerprint of the certificate that you will use to sign your application. </p> - -<p>Before you visit the registration page, use Keytool to generate the fingerprint of the appropriate certificate. - -<p>First, determine which key you will use to sign your application at release and make sure of the path to the keystore that contains it.</p> - -<p>Next, run Keytool with the <code>-list</code> option, against the target keystore and key alias. The table below lists the options you should use.</p> - -<table> -<tr> -<th>Keytool Option</th> -<th>Description</th> -</tr> -<tr> -<td><code>-list</code></td><td>Print an MD5 fingerprint of a certificate.</td> -</tr> -<tr> -<td><code>-keystore <keystore-name>.keystore</code></td><td>The name of the keystore containing the target key.</td> -</tr> -<tr> -<td><code>-storepass <password></code></td><td><p>A password for the -keystore.</p><p>As a security precaution, do not include this option -in your command line unless you are working at a secure computer. -If not supplied, Keytool prompts you to enter the password. In this -way, your password is not stored in your shell history.</p></td> -</tr> -<tr> -<td><code>-alias <alias_name></code></td><td>The alias for the key for which to generate the MD5 certificate fingerprint.</td> -</tr> -<tr> -<td><code>-keypass <password></code></td><td><p>The password for the key.</p> -<p>As a security precaution, do not include this option -in your command line unless you are working at a secure computer. -If not supplied, Keytool prompts you to enter the password. In this -way, your password is not stored in your shell history.</p></td> -</tr> -</table> - -<p>Here's an example of a Keytool command that generates an MD5 certificate fingerprint for the key <code>alias_name</code> in the keystore <code>my-release-key.keystore</code>:</p> - -<pre>$ keytool -list -alias alias_name -keystore my-release-key.keystore</pre> - -<p>Keytool will prompt you to enter passwords for the keystore and key. As output of the command, Keytool prints the fingerprint to the shell. For example:</p> - -<pre>Certificate fingerprint (MD5): 94:1E:43:49:87:73:BB:E6:A6:88:D7:20:F1:8E:B5:98</pre> - -<p>Note that, if you happen to forget your Maps API Key, you can repeat the process described above and register the fingerprint again. The server will give you the same key for the specified certificate fingerprint.</p> - -<p>Once you have the fingerprint, you can go to the Maps API registration site, described next.</p> - -<h2 id="getdebugfingerprint">Getting the MD5 Fingerprint of the SDK Debug Certificate</h2> - -<p>While you are developing and debugging your application, you will likely be -sigining your application in debug mode — that is, the SDK build tools -will automatically sign your application using the debug certificate. To let -your MapView elements properly display Maps data during this period, you should -obtain a temporary Maps API Key registered to the debug certificate. To do so, -you first need to get the MD5 fingerprint of the debug certificate. When -you are ready to release your application, you must register your release -certificate with the Google Maps service and obtain a new Maps API Key. You must -then change the MapView elements in your application to reference the new API -key. </p> - -<p>To generate an MD5 fingerprint of the debug certificate, first locate the debug keystore. The location at which the SDK tools create the default debug keystore varies by platform: </p> - -<ul> -<li>Windows Vista: <code>C:\Users\<user>\AppData\Local\Android\debug.keystore</code></li> -<li>Windows XP: <code>C:\Documents and Settings\<user>\Local Settings\Application Data\Android\debug.keystore</code></li> -<li>OS X and Linux: <code>~/.android/debug.keystore</code></li> -</ul> - -<p>If you are using Eclipse/ADT and are unsure where the debug keystore is located, you can select <strong>Windows</strong> > <strong>Prefs</strong> > <strong>Android</strong> > <strong>Build</strong> to check the full path, which you can then paste into a file explorer to locate the directory containing the keystore.</p> - -<p>Once you have located the keystore, use this Keytool command to get the MD5 fingerprint of the debug certificate:</p> - -<pre>$ keytool -list -alias androiddebugkey \ --keystore <path_to_debug_keystore>.keystore \ --storepass android -keypass android</pre> - -<h2 id="registering">Registering the Certificate Fingerprint with the Google Maps Service</h2> - -<p>When you are ready to register for a Maps API Key, load this page in a browser: </p> - -<p><a href="http://code.google.com/android/maps-api-signup.html">http://code.google.com/android/maps-api-signup.html</a></p> - -<p>To register for a Maps API Key, follow these steps:</p> - -<ol> -<li>If you don't have a Google account, use the link on the page to set one up. </li> -<li>Read the Android Maps API Terms of Service carefully. If you agree to the terms, indicate so using the checkbox on the screen. </li> -<li>Paste the MD5 certificate fingerprint of the certificate that you are registering into the appropriate form field.</li> -<li>Click "Generate API Key"</li> -</ol> - -<p>The server will handle your request, associating the fingerprint with your developer identity and generating a unique Maps API Key, then returning a results page that gives you your Key string. </p> - -<p>To use the Maps API Key string, copy and paste it into your code as described in the next section.</p> - -<h2 id="addingkey">Adding the Maps API Key to your Application</h2> - -<p>Once you've registered with the Google Maps service and have obtained a Maps API Key, you must add it to your application's MapView objects, so that the Maps server will allow them to download Maps tiles. </p> - -<p>For <code><MapView></code> elements declared in XML layout files, add the Maps API Key as the value of a special attribute — <code>android:apiKey</code>. For example: </li> - -<pre><com.google.android.maps.MapView - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:enabled="true" - android:clickable="true" - android:apiKey="example_Maps_ApiKey_String" - /></pre> -</li> - -<p>For MapView objects instantiated directly from code, pass the Maps API Key string as a parameter in the constructor. For example: </p> - -<pre>mMapView = new MapView(this, "example_Maps_ApiKey_String");</pre> - -<p>For more information about MapView, see the MapView class Documentation. </p> - -<h2 id="finalsteps">Final Steps to Enable MapView Elements</h2> - -<p>If you've added the Maps API Key to the MapViews in your application, here are the final steps to enable the MapView elements to run properly:</p> - -<ul> -<li>Make sure that you added a <code><uses-library></code> element referencing the external <code>com.google.android.maps</code> library. The element must be a child of the <code><application></code> element in the application's manifest. For example: - -<p><pre><manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.package.name"> - ... - <application android:name="MyApplication" > - <uses-library android:name="com.google.android.maps" /> - ... - </application></pre></p></li> - -<li>Sign your application with the certificate that corresponds to the Maps API Key referenced in your MapView elements. </li> - -</ul> - -<div class="special"><p>Note that, when you are ready to publish your application, you must get a Maps API Key that is based on the certificate that you will use to sign the application for release. You must then change the Maps API Key string referenced by all of your MapView elements, so that they reference the new Key. </p></div> - - - diff --git a/docs/html/guide/topics/location/index.jd b/docs/html/guide/topics/location/index.jd index 53f1d29..d7a8ff2 100644 --- a/docs/html/guide/topics/location/index.jd +++ b/docs/html/guide/topics/location/index.jd @@ -1,35 +1,43 @@ -page.title=Location +page.title=Location and Maps @jd:body <div id="qv-wrapper"> <div id="qv"> + <h2>Location and Maps quickview</h2> + <ul> + <li>Android provides a location framework that your application can use to determine the device's location and bearing and register for updates.</li> + <li>A Google Maps external library is available that lets you display and manage Maps data.</li> + </ul> <h2>In this document</h2> <ol> - <li><a href="#location">android.location</a></li> - <li><a href="#maps">com.google.android.maps</a></li> + <li><a href="#location">Location Services</a></li> + <li><a href="#maps">Google Maps External Library</a></li> + </ol> + <h2>See Also</h2> + <ol> + <li><a href="http://code.google.com/android/add-ons/google-apis/index.html">Google APIs add-on download»</a></li> </ol> </div> </div> -<p>The Android SDK includes two packages that provide Android's primary support -for building location-based services: -{@link android.location} and {@link-fixme com.google.android.maps}. -Please read on below for a brief introduction to each package.</p> +<p>Location- and maps-based applications and services are compelling for mobile device users. You can build these capabilities into your applications using the classes of the {@link android.location} package and the Google Maps external library. The sections below provide details. </p> + +<h2 id="location">Location Services</h2> -<h2 id="location">android.location</h2> +<p>Android gives your applications access to the location services supported by +the device through the classes in the <code>android.location</code> package. The +central component of the location framework is the +{@link android.location.LocationManager} system service, which provides an API to +determine location and bearing if the underlying device (if it supports location +capabilities). </p> -<p>This package contains several classes related to -location services in the Android platform. Most importantly, it introduces the -{@link android.location.LocationManager} -service, which provides an API to determine location and bearing if the -underlying device (if it supports the service). The LocationManager -should <strong>not</strong> be -instantiated directly; rather, a handle to it should be retrieved via -{@link android.content.Context#getSystemService(String) -getSystemService(Context.LOCATION_SERVICE)}.</p> +<p>As with other system services, you do not instantiate a LocationManager directly. +Rather, you request an LocationManager instance from the system by calling +{@link android.content.Context#getSystemService(String) getSystemService(Context.LOCATION_SERVICE)}. +The method returns a handle to a new LocationManager instance.</p> -<p>Once your application has a handle to the LocationManager, your application +<p>Once your application has a handle to a LocationManager instance, your application will be able to do three things:</p> <ul> @@ -42,20 +50,20 @@ will be able to do three things:</p> lat/long.</li> </ul> -<p>However, during initial development, you may not have access to real -data from a real location provider (Network or GPS). So it may be necessary to -spoof some data for your application, with some mock location data.</p> +<p>However, during initial development in the emulator, you may not have access to real +data from a real location provider (Network or GPS). In that case, it may be necessary to +spoof some data for your application using a mock location provider.</p> <p class="note"><strong>Note:</strong> If you've used mock LocationProviders in -previous versions of the SDK (m3/m5), you can no longer provide canned LocationProviders +previous versions of the SDK, you can no longer provide canned LocationProviders in the /system/etc/location directory. These directories will be wiped during boot-up. -Please follow the new procedures below.</p> - +Please follow the new procedures outlined below.</p> <h3>Providing Mock Location Data</h3> <p>When testing your application on the Android emulator, there are a couple different -ways to send it some spoof location data: with the DDMS tool or the "geo" command.</p> +ways to send it some mock location data: you can use the DDMS tool or the "geo" command +option in the emulator console.</p> <h4 id="ddms">Using DDMS</h4> <p>With the DDMS tool, you can simulate location data a few different ways:</p> @@ -67,9 +75,9 @@ ways to send it some spoof location data: with the DDMS tool or the "geo" comman <p>For more information on using DDMS to spoof location data, see the <a href="{@docRoot}guide/developing/tools/ddms.html#emulator-control">Using DDMS guide</a>. -<h4 id="geo">Using the "geo" command</h4> +<h4 id="geo">Using the "geo" command in the emulator console</h4> <p>Launch your application in the Android emulator and open a terminal/console in -your SDK's <code>/tools</code> directory. Now you can use:</p> +your SDK's <code>/tools</code> directory. Connect to the emulator console. Now you can use:</p> <ul><li><code>geo fix</code> to send a fixed geo-location. <p>This command accepts a longitude and latitude in decimal degrees, and an optional altitude in meters. For example:</p> @@ -82,28 +90,52 @@ your SDK's <code>/tools</code> directory. Now you can use:</p> </li> </ul> - -<h2 id="maps">com.google.android.maps</h2> - -<p>This package introduces a number of classes related to -rendering, controlling, and overlaying customized information on your own -Google Mapified Activity. The most important of which is the -{@link-fixme com.google.android.maps.MapView} class, which automagically draws you a -basic Google Map when you add a MapView to your layout. Note that, if you -want to do so, then your Activity that handles the -MapView must extend {@link-fixme com.google.android.maps.MapActivity}. </p> - -<p>Also note that you must obtain a MapView API Key from the Google Maps -service, before your MapView can load maps data. For more information, see -<a href="{@docRoot}guide/topics/location/geo/mapkey.html">Obtaining a MapView API Key</a>.</p> - -<p>Once you've created a MapView, you'll probably want to use -{@link-fixme com.google.android.maps.MapView#getController()} to -retrieve a {@link-fixme com.google.android.maps.MapController}, for controlling and -animating the map, and {@link-fixme com.google.android.maps.ItemizedOverlay} to -draw {@link-fixme com.google.android.maps.Overlay}s and other information on the Map.</p> - -<p>This is not a standard package in the Android library. In order to use it, you must add the following node to your Android Manifest file, as a child of the -<code><application></code> element:</p> -<pre><uses-library android:name="com.google.android.maps" /></pre> +<p>For information about how to connect to the emulator console, see +<a href="{@docRoot}guide/developing/tools/emulator.html#console">Using the Emulator Console</a>.</p> + +<h2 id="maps">Google Maps External Library</h2> + +<p>To make it easier for you to add powerful mapping capabilities to your +application, Google provides a Maps external library that includes the +com.google.android.maps package. The classes of the com.google.android.maps +package offer built-in downloading, rendering, and caching of Maps tiles, as +well as a variety of display options and controls. </p> + +<p>The key class in the Maps package is +<code>com.google.android.maps.MapView</code>, a subclass of +{@link android.view.ViewGroup ViewGroup}. A MapView displays a map with data obtained +from the Google Maps service. When the MapView has focus, it will capture +keypresses and touch gestures to pan and zoom the map automatically, including +handling network requests for additional maps tiles. It also provides all of the +UI elements necessary for users to control the map. Your application can also +use MapView class methods to control the MapView programmatically and draw a +number of Overlay types on top of the map. </p> + +<p>In general, the MapView class provides a wrapper around the Google Maps API +that lets your application manipulate Google Maps data through class methods, +and it lets you work with Maps data as you would other types of Views.</p> + +<p>The Maps external library is not part of the standard Android library, so it +may not be present on some compliant Android-powered devices (although it is +likely to be present on most devices). Similarly, the Maps external library is +not included in the standard Android library provided in the SDK. So that you +can develop using the classes of the com.google.android.maps package, the Maps +external library is made available to you as part of the Google APIs add-on for +the Android SDK. </p> + +<p>To learn more about the Maps external library and how to download and use the +Google APIs add-on, visit</p> + +<p style="margin-left:2em;"><a +href="http://code.google.com/android/add-ons/google-apis">http://code.google.com/android/add-ons/google-apis</a></p> + +<p>For your convenience, the Google APIs add-on is also included in the Android +SDK. <!-- To learn now to use the Maps external library in your application, see +[[Using External Libraries]].--></p> + +<p class="note"><strong>Note:</strong> In order to display Google Maps data in a +MapView, you must register with the Google Maps service and obtain a Maps API +Key. For information about how to get a Maps API Key, see <a +href="http://code.google.com/android/add-ons/google-apis/mapkey.html">Obtaining +a Maps API Key</a>.</p> diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd index 4541024..fd7d2da 100644 --- a/docs/html/guide/topics/media/index.jd +++ b/docs/html/guide/topics/media/index.jd @@ -9,7 +9,7 @@ page.title=Audio and Video <li>Audio playback and record</li> <li>Video playback</li> <li>Handles data from raw resources, files, streams</li> -<li>Built-in codecs for a variety of media. See <a href="{@docRoot}guide/appendix/media-formats.html">Android 1.0 Media Formats</a></li> +<li>Built-in codecs for a variety of media. See <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li> </ul> <h2>Key classes</h2> diff --git a/docs/html/guide/topics/media/media.jd b/docs/html/guide/topics/media/media.jd deleted file mode 100644 index 463686d..0000000 --- a/docs/html/guide/topics/media/media.jd +++ /dev/null @@ -1,172 +0,0 @@ -page.title=Media Capabilities -@jd:body - -<div class="sidebox"> - -<h3>Media Quickview</h3> - -<h4>Built-in capabilities</h4> -<ul> -<li>Audio playback and record</li> -<li>Video playback</li> -</ul> - -<h4>Data sources</h4> -<ul> -<li>Raw resources</li> -<li>Data files</li> -<li>Streams</li> -</ul> - -<h4>Media Formats</h4> -<ul> -<li>See appendix <a href="{@docRoot}devguide/appendix/media_formats.html">Android 1.0 Media Formats</a></li> -</ul> - -<h4>Key APIs</h4> -<ul> -<li>{@link android.media.MediaPlayer} (playback, all audio and video formats)</li> -<li>{@link android.media.MediaRecorder} (record, all audio formats)</li> -</ul> -</div> - -<p>The Android platform offers built-in encoding/decoding for a variety of common media types, -so that you can easily integrate audio, video, and images into your applications. Accessing the platform's media -capabilities is fairly straightforward &mdash you do so using the same intents and -activities mechanism that the rest of Android uses.</p> - -<p>Android lets you play audio and video from several types of data sources. You can play audio or video from media files stored in the application's resources (raw resources), from standalone files in the filesystem, or from a data stream arriving over a network connection. To play audio or video from your application, use the {@link android.media.MediaPlayer} class.</p> - -<p>The platform also lets you record audio, where supported by the mobile device hardware. Recording of video is not currently supported, but is planned for a future release. To record audio, use the -{@link android.media.MediaRecorder} class. Note that the emulator doesn't have hardware to capture audio, but actual mobile devices are likely to provide these capabilities that you can access through MediaRecorder. </p> - -<p>For a list of the media formats for which Android offers built-in support, see the <a href="{@docRoot}devguide/appendix/media_formats.html">Android Media Formats</a> appendix. </p> - -<h2>Playing Audio and Video</h2> -<p>Media can be played from anywhere: from a raw resource, from a file from the system, -or from an available network (URL).</p> - -<p>You can play back the audio data only to the standard -output device; currently, that is the mobile device speaker or Bluetooth headset. You -cannot play sound files in the conversation audio. </p> - -<h3>Playing from a Raw Resource</h3> -<p>Perhaps the most common thing to want to do is play back media (notably sound) -within your own applications. Doing this is easy:</p> -<ol> - <li>Put the sound (or other media resource) file into the <code>res/raw</code> - folder of your project, where the Eclipse plugin (or aapt) will find it and - make it into a resource that can be referenced from your R class</li> - <li>Create an instance of <code>MediaPlayer</code>, referencing that resource using - {@link android.media.MediaPlayer#create MediaPlayer.create}, and then call - {@link android.media.MediaPlayer#start() start()} on the instance:<br><br></li> -</ol> -<pre> - MediaPlayer mp = MediaPlayer.create(context, R.raw.sound_file_1); - mp.start(); -</pre> -<p>To stop playback, call {@link android.media.MediaPlayer#stop() stop()}. If -you wish to later replay the media, then you must -{@link android.media.MediaPlayer#reset() reset()} and -{@link android.media.MediaPlayer#prepare() prepare()} the MediaPlayer object -before calling {@link android.media.MediaPlayer#start() start()} again. -(<code>create()</code> calls <code>prepare()</code> the first time.)</p> -<p>To pause playback, call {@link android.media.MediaPlayer#pause() pause()}. -Resume playback from where you paused with -{@link android.media.MediaPlayer#start() start()}.</p> - -<h3>Playing from a File or Stream</h3> -<p>You can play back media files from the filesystem or a web URL:</p> -<ol> - <li>Create an instance of the <code>MediaPlayer</code> using <code>new</code></li> - <li>Call {@link android.media.MediaPlayer#setDataSource setDataSource()} - with a String containing the path (local filesystem or URL) - to the file you want to play</li> - <li>First {@link android.media.MediaPlayer#prepare prepare()} then - {@link android.media.MediaPlayer#start() start()} on the instance:<br><br></li> -</ol> -<pre> - MediaPlayer mp = new MediaPlayer(); - mp.setDataSource(PATH_TO_FILE); - mp.prepare(); - mp.start(); -</pre> -<p>{@link android.media.MediaPlayer#stop() stop()} and -{@link android.media.MediaPlayer#pause() pause()} work the same as discussed -above.</p> - <p class="note"><strong>Note:</strong> It is possible that <code>mp</code> could be - null, so good code should <code>null</code> check after the <code>new</code>. - Also, <code>IllegalArgumentException</code> and <code>IOException</code> either - need to be caught or passed on when using <code>setDataSource()</code>, since - the file you are referencing may not exist.</p> -<p class="note"><strong>Note:</strong> -If you're passing a URL to an online media file, the file must be capable of -progressive download.</p> - -<h2>Recording Media Resources</h2> -<p>Recording media is a little more involved than playing it back, as you would -probably expect, but it is still fairly simple. There is just a little more set -up to do</p> -<ol> - <li>Create a new instance of {@link android.media.MediaRecorder - android.media.MediaRecorder} using <code>new</code></li> - <li>Create a new instance of {@link android.content.ContentValues - android.content.ContentValues} and put in some standard properties like - <code>TITLE</code>, <code>TIMESTAMP</code>, and the all important - <code>MIME_TYPE</code></li> - <li>Create a file path for the data to go to (you can use {@link - android.content.ContentResolver android.content.ContentResolver} to - create an entry in the Content database and get it to assign a path - automatically which you can then use)</li> - <li>Set the audio source using {@link android.media.MediaRecorder#setAudioSource - MediaRecorder.setAudioSource()}. You will probably want to use - <code>MediaRecorder.AudioSource.MIC</code></li> - <li>Set output file format using {@link - android.media.MediaRecorder#setOutputFormat MediaRecorder.setOutputFormat()} - </li> - <li>Set the audio encoder using - {@link android.media.MediaRecorder#setAudioEncoder MediaRecorder.setAudioEncoder()} - </li> - <li>Finally, {@link android.media.MediaRecorder#prepare prepare()} and - {@link android.media.MediaRecorder#start start()} the recording. - {@link android.media.MediaRecorder#stop stop()} and - {@link android.media.MediaRecorder#release release()} when you are done</li> -</ol> -<p>Here is a code example that will hopefully help fill in the gaps:</p> -<p><strong>Start Recording</strong></p> -<pre> - recorder = new MediaRecorder(); - ContentValues values = new ContentValues(3); - - values.put(MediaStore.MediaColumns.TITLE, SOME_NAME_HERE); - values.put(MediaStore.MediaColumns.TIMESTAMP, System.currentTimeMillis()); - values.put(MediaStore.MediaColumns.MIME_TYPE, recorder.getMimeContentType()); - - ContentResolver contentResolver = new ContentResolver(); - - Uri base = MediaStore.Audio.INTERNAL_CONTENT_URI; - Uri newUri = contentResolver.insert(base, values); - - if (newUri == null) { - // need to handle exception here - we were not able to create a new - // content entry - } - - String path = contentResolver.getDataFilePath(newUri); - - // could use setPreviewDisplay() to display a preview to suitable View here - - recorder.setAudioSource(MediaRecorder.AudioSource.MIC); - recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); - recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); - recorder.setOutputFile(path); - - recorder.prepare(); - recorder.start(); -</pre> -<p><strong>Stop Recording</strong></p> -<pre> - recorder.stop(); - recorder.release(); -</pre> - diff --git a/docs/html/guide/tutorials/views/hello-mapview.jd b/docs/html/guide/tutorials/views/hello-mapview.jd index 976b8ab..30b92c4 100644 --- a/docs/html/guide/tutorials/views/hello-mapview.jd +++ b/docs/html/guide/tutorials/views/hello-mapview.jd @@ -3,6 +3,32 @@ parent.title=Hello, Views parent.link=index.html @jd:body +<div class="special"> +<p>This tutorial requires that you have the Google Maps external library +installed in your SDK environment. By default the Android 1.5 SDK includes the +Google APIs add-on, which in turn includes the Maps external library. If you +don't have the Google APIs SDK add-on, you can download it from this +location:</p> + +<p style="margin-left:2em;"><a +href="http://code.google.com/android/add-ons/google-apis">http://code.google.com/android/add-ons/google-apis</a></p> + +<p>The Google APIs add-on requires Android 1.5 SDK or later release. After +installing the add-on in your SDK, set your project properties to use the build +target called "Google APIs Add-on". See the instructions for setting a build +target in <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing in +Eclipse with ADT</a> or <a +href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>, +as appropriate for your environment. </p> + +<p>You will also need to use the android tool to set up an AVD that uses the +Google APIs deployment target. See <a +href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> for +more information. Once you have set up your environment, you will be able to +build and run the project described in this tutorial</a></p> + +</div> + <p>A MapView allows you to create your own map-viewing Activity. First, we'll create a simple Activity that can view and navigate a map. Then we will add some overlay items.</p> diff --git a/docs/html/index.jd b/docs/html/index.jd index bd681e2..cc609a3 100644 --- a/docs/html/index.jd +++ b/docs/html/index.jd @@ -12,7 +12,7 @@ home=true <!-- total max width is 520px --> <img src="{@docRoot}assets/images/home/IO-logo.png" alt="Google I/O Developer Conference 2009" width="242px" /> <div id="announcement" style="width:270px"> - <p>Google I/O is a two-day developer event that will take place May 27-28 at Moscone Center, San Francisco.</p> + <p>Google I/O is a two-day developer event that will take place May 27-28 at Moscone Center, San Francisco. The agenda includes a number of great sessions on Android topics by team engineers and other developers.</p> <p><a href="http://code.google.com/events/io/">Learn more »</a></p> </div> <!-- end annoucement --> </div> <!-- end annoucement-block --> @@ -116,10 +116,10 @@ home=true 'sdk': { 'layout':"imgLeft", 'icon':"sdk-small.png", - 'name':"SDK 1.1 r1", + 'name':"SDK 1.5 r1", 'img':"sdk-large.png", - 'title':"Android 1.1 SDK r1", - 'desc': "<p>A new Android SDK is available for download. The new SDK includes minor API changes, new UI localizations, bug fixes and some new application features.</p><p><a href='{@docRoot}sdk/1.1_r1/index.html'>Download Android 1.1 SDK r1</a></p>" + 'title':"Android 1.5 SDK r1", + 'desc': "<p>The final version of the Android 1.5 SDK is now available. It includes new APIs for Android 1.5, updated developer tools, multiple platform versions, and a Google APIs Add-on.</p><p><a href='{@docRoot}sdk/1.5_r1/index.html'>Download Android 1.5 SDK</a></p>" }, 'mapskey': { @@ -128,7 +128,7 @@ home=true 'name':"Maps API Key", 'img':"maps-large.png", 'title':"Maps API Key", - 'desc':"<p>If you're writing an Android application that uses Google Maps (with MapView), you must register your application to obtain a Maps API Key. Without the key, your maps application will not work on Android devices. Obtaining a key requires just a couple of steps.</p><p><a href='{@docRoot}guide/topics/location/geo/mapkey.html'>Learn how to get a Maps API Key</a></p>" + 'desc':"<p>If you're writing an Android application that uses Google Maps (with MapView), you must register your application to obtain a Maps API Key. Without the key, your maps application will not work on Android devices. Obtaining a key requires just a couple of steps.</p><p><a href='{@docRoot}guide/topics/location/index.html'>Learn more...</a></p>" }, 'market': { diff --git a/docs/html/maps-api-signup.html b/docs/html/maps-api-signup.html deleted file mode 100644 index a604b2a..0000000 --- a/docs/html/maps-api-signup.html +++ /dev/null @@ -1,369 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html> - <head> - -<meta http-equiv="content-type" content="text/html; charset=utf-8"/> -<title>Sign Up for the Android Maps API - Android Maps API - Google Code</title> -<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet"></link> -<script src="http://code.google.com//js/codesite.pack.01312008.js" type="text/javascript"></script> -<link rel="search" type="application/opensearchdescription+xml" title="Google Code" href="/osd.xml" /> - -<!--[if IE]><link rel="stylesheet" type="text/css" href="/css/iehacks.css" /><![endif]--> - - -<script type="text/javascript"> -//<![CDATA[ - -function CheckForm(form) { - if (!form["agreeTerms"].checked) { - alert("To get an Android Maps API key, " + - "you must agree to the API terms by checking the checkbox."); - } else { - var fp = form["fp"].value; - if (fp.length < 32) { - alert("Please enter the MD5 fingerprint of the certificate you will use to sign your Android Application."); - form["fp"].focus(); - } else { - top.location = "http://www.google.com/glm/mmap/a/api?fp=" + - encodeURIComponent(fp); - } - } - return false; -} - -//]]> -</script> - </head> - - <body class="gc-documentation"> - <div id="gc-container"> -<a name="top"></a> -<div id="skipto"> - - -</div> -<div id="gc-header"> - <div id="logo"><a href="/"> - - <img src="/images/cleardot.gif" height="1px" width="1px" alt="Google Code Home Page" id="gc-logo-img"/> - - </a></div> - <div id="search"> - <div id="searchForm" class="searchForm" style="display:none"> - <form action="" accept-charset="utf-8" class="gsc-search-box" onsubmit="executeGSearch(document.getElementById('gsearchInput').value); return false;"> - <table class="gsc-search-box" cellpadding="0" cellspacing="0"> - <tbody> - <tr> - <td class="gsc-input"> - <input id="gsearchInput" type="text" name="q" maxlength="2048" class="gsc-input" autocomplete="off" title="Google Code Search" style="width:345px"/> - </td> - <td class="gsc-search-button"> - <div id='cs-searchresults' onclick='event.cancelBubble = true;'></div> - <input title="Search" id="gsearchButton" class="gsc-search-button" value="Search" type="submit"/> - </td> - </tr> - <tr> - <td class="greytext">e.g. "ajax apis" or "open source"</td> - </tr> - </tbody> - </table> - </form> - </div> <!-- end searchForm --> - <div id="searchForm2" class="searchForm2" style="display:block"> - <form id="cse" action="http://www.google.com/cse"> - <input type="hidden" name="cref" value="http://code.google.com/cse/googlecode-context.xml" /> - <input type="text" name="q" maxlength="2048" autocomplete="off" title="Google Code Search" style="width:345px"/> - <input type="submit" name="sa" value="Search" title="Search"/><br/> - <div class="greytext">e.g. "ajax apis" or "open source"</div> - </form> - </div> <!-- end searchForm2 --> - </div> <!-- end search --> -</div> <!-- end gc-header --> - - -<div id="codesiteContent"> - -<a name="gc-topnav-anchor"></a> -<div id="gc-topnav"> - <h1>Android Maps API Key Signup</h1> - <ul id="docs" class="gc-topnav-tabs"> - <li id="home_link"> - <a href="/android/" title="Android Developer Site">Home</a> - </li> - - <li id="docs_link"> - <a href="/android/toolbox/apis/lbs.html" title="Android Maps API Documentation">Docs</a> - </li> - - <li> - <a href="http://googlegeodevelopers.blogspot.com/" title="Official Google Maps API blog">Maps Blog</a> - </li> - - <li> - <a href="http://android-developers.blogspot.com/" title="Official Android Developers Blog">Android Blog</a> - </li> - </ul> -</div> <!-- end gc-topnav --> - - -<div> -<!-- - <div class="g-section g-tpl-170"> - - <a name="gc-toc-anchor"></a> - <div class="g-unit g-first" id="gc-toc"> - <ul> - <li>Add some sidebar content?</li> - </ul> - <div class="line"></div> - </div> ---> - - <a name="gc-pagecontent-anchor"></a> - <div class="g-unit" id="gc-pagecontent"> - <h1 class="page_title">Sign Up for the Android Maps API</h1> - -<p>The Android Maps API lets you embed -<a href="/android/reference/com/google/android/maps/MapView.html">Google -Maps</a> in your own Android applications. A single Maps API key is -valid for all applications signed by a single certificate. See -this <a href="/android/intro/develop-and-debug.html#signing">documentation -page</a> for more information about application signing. To get a -Maps API key for your certificate, you will need to provide its the certificate's -fingerprint. This can be obtained using Keytool. For example, on -Linux or Mac OSX, you would examine your debug keystore like this: -<pre class="prettyprint">$ keytool -list -keystore ~/.android/debug.keystore -... -Certificate fingerprint (MD5): 94:1E:43:49:87:73:BB:E6:A6:88:D7:20:F1:8E:B5:98 -</pre> - -<p>If you use different keys for signing development builds and -release builds, you will need to obtain a separate Maps API key for -each certificate. Each key will only work in applications signed by -the corresponding certificate.</p> - -<p>You also need a <a href="http://www.google.com/accounts/">Google Account</a> -to get a Maps API key, and your API key will be connected to your Google Account.</p> -<br/> -<div id="termsbox" style="margin-left: 2em"> -<textarea rows="15" cols="70" readonly="readonly" onfocus="this.blur()"> -Android Maps APIs Terms of Service - -Last Updated: October 13, 2008 - -Thanks for your interest in the Android Maps APIs. The Android Maps APIs are a collection of services (including, but not limited to, the "com.google.android.maps.MapView" and "android.location.Geocoder" classes) that allow you to include maps, geocoding, and other content from Google and its content providers in your Android applications. The Android Maps APIs explicitly do not include any driving directions data or local search data that may be owned or licensed by Google. - - -1. Your relationship with Google. - 1.1. Your use of any of the Android Maps APIs (referred to in this document as the "Maps API(s)" or the "Service") is subject to the terms of a legal agreement between you and Google Inc., whose principal place of business is at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States ("Google"). This legal agreement is referred to as the "Terms." - 1.2. Unless otherwise agreed in writing with Google, the Terms will include the following: 1) the terms and conditions set forth in this document (the "Maps APIs Terms"); 2) the Legal Notices (http://www.google.com/intl/en-us/help/legalnotices_maps.html); and 3) the Privacy Policy (http://www.google.com/privacy.html). Before you use the Maps APIs, you should read each of the documents comprising the Terms, and print or save a local copy for your records. - 1.3. If you use the Maps APIs in conjunction with any other Google products or services, including any other Google API, (collectively, the "Services"), your agreement with Google will also include the terms applicable to those Services. All of these are referred to as the "Additional Terms." If Additional Terms apply, they will be accessible to you either within or through your use of that Service. If there is any contradiction between what any Additional Terms say and what the Maps APIs Terms say, then the Maps APIs Terms will take precedence only as it relates to the Maps APIs, and not to any other Services. - 1.4. Google reserves the right to make changes to the Terms from time to time. When these changes are made, Google will make a new copy of the Terms available at http://code.google.com/android/maps-api-tos.pdf. You understand and agree that if you use the Service after the date on which the Terms have changed, Google will treat your use as acceptance of the updated Terms. If a modification is unacceptable to you, you may terminate the agreement by ceasing use of the Maps APIs as well distribution of any applications that use the Maps APIs. - 1.5. Definitions - (a) "Content" means any content provided through the Service, including map and terrain data, photographic imagery, traffic data, or any other content. - (b) "Maps API Implementation" means a software application that uses the Maps APIs to obtain and display Content in conjunction with Your Content, according to these Terms. - (c) "Your Content" means any content that you provide in your Maps API Implementation, including data, images, video, or software. Your Content does not include the Content. - - -2. Accepting the Terms - 2.1. In order to use the Maps APIs you must agree to the Terms. You can accept the Terms by: (a) clicking to accept or agree to the Terms, where this option is made available to you by Google in the user interface for the Service; or (b) using the Maps APIs. In this case, you understand and agree that Google will treat your use of the Maps APIs as acceptance of the Terms from that point onwards. - 2.2. You may not use the Maps APIs and may not accept the Terms if you are a person barred from using the Service under the laws of the United States or the country in which you are resident or from which you use the Service. - 2.3. You represent that you have full power, capacity and authority to accept these Terms. If you are accepting on behalf of your employer or another entity, you represent that you have full legal authority to bind your employer or such entity to these Terms. If you don't have the legal authority to bind, please ensure that an authorized person from your entity consents to and accepts these Terms. - - -3. Privacy and Personal Information - 3.1. For information about Google's data protection practices, please read Google's Privacy Policy at http://www.google.com/privacy.html. This policy explains how Google treats your personal information and protects your privacy when you use the Service. - 3.2. You agree to the use of your data in accordance with Google's Privacy Policy. - - -4. Provision of Service by Google - 4.1. Google has subsidiaries and affiliated legal entities around the world ("Subsidiaries and Affiliates"). Sometimes, these companies will be providing the Service to you on behalf of Google itself. You acknowledge and agree that Subsidiaries and Affiliates will be entitled to provide the Service to you. - 4.2. Google is constantly innovating in order to provide the best possible experience for its users. You acknowledge and agree that the form and nature of the Service that Google provides may change from time to time without prior notice to you. As part of this continuing innovation, you acknowledge and agree that Google may stop (temporarily or permanently) providing the Service (or any features within the Service) to you or to users generally at Google's sole discretion, without prior notice to you. Google reserves the right to refuse or discontinue the Service to anyone, and to disable users' access to the Service, including the Maps APIs or any Content, at any time in its sole discretion with or without notice. - 4.3. You acknowledge and agree that Google may impose or adjust the limit on the number of transactions you may send or receive through the Service; such fixed upper limits may be set by Google at any time, at Google's discretion. - 4.4. Google reserves the right to release subsequent versions of the Maps APIs and to require you to obtain and use the most recent version. - 4.5. The Service currently does not include advertising in the Content. However, Google reserves the right to include advertising in the Content provided to you through the Service, but will provide you with sixty (60) days notice prior to the commencement of advertising. Such notice may be provided on relevant Google websites, including but not limited to theÿGoogle Maps API Blog (http://googlemapsapi.blogspot.com) and theÿGoogle Maps API Groupÿ(http://groups.google.com/group/Google-Maps-API) or such successor URLs that Google may designate from time to time. During that 60 day period, you may terminate your use of the Service, or provide notice of your refusal to accept advertising in accordance with Google's policies and procedures for providing such notice (which Google may make available from time to time in its sole discretion). - - -5. Use of the Service by You - 5.1. In order to access the Service, you must have a Google Account. You agree that any information you give to Google in connection with your Google Account or your continued use of the Service will always be accurate, correct and up to date. - 5.2. After supplying Google with your account information and the MD5 fingerprint for the certificate used to sign your application, and accepting the Terms, you will be issued an alphanumeric key assigned to you by Google that is uniquely associated with your Google Account and the application certificate. Your Maps API implementation?s MapView must include this alphanumeric key, either using the "android:apiKey" XML attribute or using the appropriate MapView constructor, as described in the Android MapView documentation (http://code.google.com/android/reference/com/google/android/maps/MapView.html). - 5.3. There is currently no limit to the number of keys you may obtain in this manner provided that you use a different certificate for each key you obtain and that you use the same Google Account for every key you obtain. You agree that each key is only valid for applications signed with the corresponding certificate. You agree that Google may, in its sole discretion, impose a limit on the number of keys that may be obtained in the future. You agree that your continued use of any of the keys assigned by Google or distribution of any applications using such keys constitutes your continued agreement to these Terms. - 5.4. Subject to these Terms, you may develop, display and/or distribute your Maps API Implementation as part of a commercial or non-commercial enterprise. - 5.5. Your Maps API Implementation and Your Content must not violate Google's Software Principles available at http://www.google.com/intl/en/corporate/software_principles.html (or such successor URL as Google may provide) and any other policies as Google may develop from time to time and make available to you. - 5.6. You agree to use the Service only for purposes that are permitted by: (1) the Terms; (2) any applicable third-party contract, law, or regulation; and (3) any applicable policies or guidelines made available by Google. By way of example, and not as a limitation, you agree that when using the Service, you will not - a. defame, abuse, harass, stalk, threaten or otherwise violate the legal rights (such as rights of privacy and publicity) of others; - b. upload, post, transmit or otherwise make available any inappropriate, defamatory, obscene, or unlawful content; - c. upload, post, transmit or otherwise make available any content that infringes any patent, trademark, copyright, trade secret or other proprietary right of any party, unless you are the owner of the rights, or have the permission of the owner or other legal justification to use such content; - d. upload, post, transmit or otherwise make available messages that promote pyramid schemes, chain letters, or disruptive commercial messages or advertisements; - e. download any file posted by another that you know, or reasonably should know, cannot legally be distributed in such manner; - f. impersonate another person or entity, or falsify or delete any author attributions or labels of the origin or source of Content, or other material; - g. restrict or inhibit any other users from using and enjoying the Service; - h. remove, obscure, or fail to display the Terms of Use link as presented through the Service or described in the Service documentation; - i. remove, alter, or obscure any copyright, trademark or other proprietary rights notices or labels of origin or proprietary rights designation contained in or on Google Services or Content; - j. delete, obscure, or in any manner alter any warning, notice (not limited to any copyright or other proprietary rights notice), or link which appears in the Service or the Content - k. interfere with or disrupt Google Services or servers or networks connected to Google Services, or disobey any requirements, procedures, policies or regulations of networks connected to Google Services; - l. use any robot, spider, site search/retrieval application, or other device to retrieve or index any portion of the Service or Content or collect information about users for any unauthorized purpose; - m. display content in your Maps API Implementation that falsely expresses or implies that such content is sponsored or endorsed by Google; - n. create user accounts by automated means or under false or fraudulent pretenses, or obtain or attempt to obtain keys for the Service using multiple Google Accounts; - o. promote or provide instructional information about illegal activities; - p. promote physical harm or injury against any group or individual; or - q. transmit any viruses, worms, defects, Trojan horses, or any items of a destructive nature. - 5.7. You agree that if you use the Service to develop a Maps API Implementation for use by other users, you will protect the privacy and legal rights of those users. If your Maps API Implementation provides you or another party with information about users, including but not limited to personally identifiable information or non-personally identifiable usage information, you must make the users aware that the information will be available to you or another party, and you must provide legally adequate privacy notice and protection for those users. If your application stores information submitted by users, it must do so securely. If your Maps API Implementation allows a user to provide you with Google Account information, you may only use that information to access the user's Google Account when, and for the limited purposes for which, the user has given you permission to do so. - 5.8. You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the Terms or any applicable law or regulation, and for the consequences (including any loss or damage which Google may suffer) of any such breach. - - -6. Google?s Proprietary Rights - 6.1. Ownership. You acknowledge and agree that Google (or Google's licensors and their suppliers, as applicable) own all legal right, title and interest in and to the Service and Content, including any intellectual property rights that subsist in the Service and Content (whether those rights happen to be registered or not, and wherever in the world those rights may exist). - 6.2. Brand Feature License. For purposes of these Terms, "Brand Features" will mean the trade names, trademarks, service marks, logos, domain names, and other distinctive brand features of each party, respectively, as secured by such party from time to time. Google grants to you a nontransferable, nonsublicenseable, nonexclusive license during the Term to display Google's Brand Features for the purpose of promoting or advertising that you use the Service in accordance with this Section 6.2 and for the purpose of fulfilling your obligations under Section 6.5 below. You grant to Google a nontransferable, nonexclusive license during the Term to use Your Brand Features to advertise that you are using the Service. In using Google Brand Features, you will not: - a. display a Google Brand Feature in any manner that implies a relationship or affiliation with, sponsorship, or endorsement by Google, other than your use of the Service, or that can be reasonably interpreted to suggest editorial content has been authored by, or represents the views or opinions of Google or Google personnel; - b. use Google Brand Features to disparage Google, its products or Services; - c. display a Google Brand Feature on your site if it contains or displays adult content or promotes illegal activities, gambling, or the sale of tobacco or alcohol to persons under twenty-one (21) years of age; - d. have the Google logo as the largest logo in your application (except as displayed in the map image itself); - e. display a Google Brand Feature as the most prominent element in any part of your application; - f. display a Google Brand Feature in a manner that is misleading, defamatory, infringing, libelous, disparaging, obscene or otherwise objectionable to Google; - g. display a Google Brand Feature on a site that violates any law or regulation; or - h. remove, distort or alter any element of a Google Brand Feature (this includes squeezing, stretching, inverting, discoloring, etc.). - 6.3. You understand and agree that Google has the sole discretion to determine whether your use of Google brand features is in accordance with the above restrictions. - 6.4. Except as set forth in this Section 6, nothing in the Terms will grant or will be deemed to grant to one party any right, title or interest in or to the other party's Brand Features. All use by you of Google's Brand Features (including any goodwill associated therewith) will inure to the benefit of Google. At no time during or after the Term will you challenge or assist others to challenge the Brand Features of Google (except to the extent such restriction is prohibited by law) or the registration thereof by Google, nor will you attempt to register any Brand Features (including domain names) that are confusingly similar in any way (including but not limited to, sound, appearance and spelling) to those of Google. - 6.5. You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices, Terms of Use links, or Brand Features) that may be affixed to or provided through the Service. Where such notices are not affixed within the Service, you agree to display such notices according to the Service documentation if so specified. - - -7. License from Google - 7.1. Service. Google gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the Service as provided by Google, in the manner permitted by the Terms. - 7.2. Content. Google gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to access, use, publicly perform and publicly display the Content in your Maps API Implementation, as the Content is provided in the Service, and in the manner permitted by the Terms. Specifically, you understand the following: - a. Content, not limited to map data, traffic, and directions, is provided for planning purposes only. You may find that weather conditions, construction projects, closures, or other events may cause road conditions or directions to differ from the results depicted in the Content. You should exercise judgment in your use of the Content. - b. Certain Content is provided under license from third parties (http://www.google.com/intl/en_us/help/legalnotices_maps.html), including Tele Atlas B.V. ("Tele Atlas"), and is subject to copyright and other intellectual property rights owned by or licensed to Tele Atlas and/or such third parties. You may be held liable for any unauthorized copying or disclosure of this content. Your use of Tele Atlas map data is subject to additional restrictions located in the Legal Notices (http://www.google.com/intl/en_us/help/legalnotices_maps.html) page. - 7.3. In addition to the license granted here, you may use certain Content according to the terms set forth in our Permission Guidelines for Google Maps and Google Earth (http://www.google.com/permissions/geoguidelines.html). - 7.4. U.S. Government Restricted Rights. If the Service is being used or accessed by or on behalf of the United States government, such use is subject to additional terms located in the "Government End Users" section of our Legal Notices (http://www.google.com/intl/en_us/help/legalnotices_maps.html) page. - 7.5. Google reserves the sole right and discretion to determine whether your use of the Service and Content is in conformance with these Terms. - - -8. License Restrictions. Except as expressly permitted under the Terms, or unless you have received prior written authorization from Google (or, as applicable, from the provider of particular Content), the license granted to you in Section 7 is conditioned on your adherence to all of the restrictions in this Section 8. Under this Section 8, you must not (nor may you permit anyone else to): - 8.1. access or use the Service or any Content through any technology or means other than those provided in the Service, or through other explicitly authorized means Google may designate; - 8.2. copy, translate, modify, create a derivative work of, pre-fetch, cache, or publicly display any Content or any part thereof. - 8.3. redistribute, sublicense, rent, publish, sell, assign, lease, market, transfer, or otherwise make the Service or Content available to third parties; - 8.4. reverse engineer, decompile or otherwise attempt to extract the source code of the Service or any part thereof, unless this is expressly permitted or required by applicable law; - 8.5. use the Service in a manner that gives your or any other person access to mass downloads or bulk feeds of any Content, including but not limited to numerical latitude or longitude coordinates; - 8.6. delete, obscure, or in any manner alter any warning, notice (including but not limited to any copyright or other proprietary rights notice), or link that appears in the Service or the Content; - 8.7. use the Service or Content with any products, systems, or applications for or in connection with (a) real time navigation or route guidance based on position input from a sensor (including but not limited to any visual or audible turn-by-turn route guidance); or (b) any systems or functions for automatic or autonomous control of vehicle behavior; or (c) dispatch, fleet management, business asset tracking, or similar enterprise applications (for avoidance of doubt, you are permitted to use the Service to create Maps API Implementations to track people or assets equipped with a sensor, where the tracking of the people or assets is not critical to the core business or service of the application user. For example, you are permitted to use the Maps APIs to create "Friend Finder" applications that allow consumers to track the locations of their friends? mobile devices, but you are not permitted to use the Maps APIs to create "Business Asset Tracking" applications that track or locate business or government users? field sales or field service personnel, vehicles or other assets that are critical (not incidental) to the core business or service of the application user); - 8.8 print more than 5,000 copies of sales collateral materials containing a screenshot with Tele Atlas Content for commercial sales lead generation ("Direct Marketing"); (if you desire (a) to use Tele Atlas Content for Direct Marketing in excess of the above amount, or (b) to incorporate Tele Atlas Content as a core part of printed matter (such as printed maps or guide books) that you redistribute for a fee, you must contact Tele Atlas to obtain a license to do so); or - 8.9 offer a professional batch geocoding service that uses the Content contained in any Google Services. - - -9. Content License from You - 9.1. You retain copyright and any other rights you already hold in Your Content. If you decide to submit or post Your Content to Google, you give Google a perpetual, irrevocable, worldwide, royalty-free, and non-exclusive license to reproduce, adapt, modify, translate, publish, publicly perform, publicly display and distribute Your Content. This license is solely for the purpose of enabling Google to display, distribute and promote the Service. - 9.2. You agree that this license includes a right for Google to make such Content available to other companies, organizations or individuals with whom Google has relationships for the provision of syndicated services, and to use such Content in connection with the provision of those services. - 9.3. You understand that Google, in performing the required technical steps to provide the Service to our users, may (a) transmit or distribute your Content over various public networks and in various media; and (b) make such changes to your Content as are necessary to conform and adapt that Content to the technical requirements of connecting networks, devices, services or media. You agree that this license will permit Google to take these actions. - 9.4. You confirm and warrant to Google that you have all the rights, power and authority necessary to grant the above license. - - -10. Your Passwords and Account Security - 10.1. You agree and understand that you are responsible for maintaining the confidentiality of passwords or developer keys associated with any account you use to access the Service. Accordingly, you agree that you will be solely responsible to Google for your use of the Service including, but not limited to, activities that occur under your account or developer key. If you become aware of any unauthorized use of your password or of your account, you agree to notify Google immediately. - - -11. Terminating this Agreement - 11.1. The Terms will continue to apply until terminated by either you or Google as set out below. - 11.2. You may terminate your legal agreement with Google by discontinuing your use of the Service at any time, removing the Maps API code from your Maps API Implementation, and ceasing the distribution of any Maps API Implementation that uses the Maps API. You do not need to specifically inform Google when you stop using the Service. - 11.3. Google may, at any time, terminate its legal agreement with you at its discretion without prior notice to you. - 11.4. Nothing in this Section will affect Google's rights regarding provision of the Service under Section 4 of the Terms. - 11.5. When this legal agreement comes to an end, those Terms that by their nature are intended to continue indefinitely will continue to apply, including but not limited to Sections 6.1, 6.3 and 6.4 (Google?s Proprietary Rights); 11.4 and 11.5 (Terminating this Agreement); 12 (Exclusion of Warranties); 13 (Limitation of Liability); 14 (Indemnity); and 18 (General Legal Terms). - - -12. EXCLUSION OF WARRANTIES - 12.1. NOTHING IN THESE TERMS, INCLUDING SECTIONS 12 AND 13, WILL EXCLUDE OR LIMIT GOOGLE'S WARRANTY OR LIABILITY FOR LOSSES WHICH MAY NOT BE LAWFULLY EXCLUDED OR LIMITED BY APPLICABLE LAW. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF CERTAIN WARRANTIES OR CONDITIONS OR THE LIMITATION OR EXCLUSION OF LIABILITY FOR CERTAIN TYPES OF LOSS OR DAMAGES. ACCORDINGLY, ONLY THE LIMITATIONS THAT ARE LAWFUL IN YOUR JURISDICTION WILL APPLY TO YOU, AND GOOGLE?S LIABILITY WILL BE LIMITED TO THE MAXIMUM EXTENT PERMITTED BY LAW. - 12.2. YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SERVICE AND THE CONTENT IS AT YOUR SOLE RISK AND THAT THE SERVICE AND THE CONTENT ARE PROVIDED "AS IS" AND "AS AVAILABLE." IN PARTICULAR, GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS AND THEIR SUPPLIERS, DO NOT REPRESENT OR WARRANT TO YOU THAT: - a. YOUR USE OF THE SERVICE WILL MEET YOUR REQUIREMENTS; - b. YOUR USE OF THE SERVICE WILL BE UNINTERRUPTED, TIMELY, SECURE OR FREE FROM ERROR; - c. ANY INFORMATION OBTAINED BY YOU AS A RESULT OF YOUR USE OF THE SERVICES WILL BE ACCURATE OR RELIABLE; AND - d. THAT DEFECTS IN THE OPERATION OR FUNCTIONALITY OF ANY SOFTWARE PROVIDED TO YOU AS PART OF THE SERVICES WILL BE CORRECTED. - 12.3. ANY CONTENT OBTAINED THROUGH THE USE OF THE SERVICES IS DONE AT YOUR OWN DISCRETION AND RISK AND YOU WILL BE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE, LOSS OF DATA, OR ANY OTHER DAMAGE OR INJURY THAT RESULTS FROM THE DOWNLOAD OR USE OF ANY SUCH CONTENT. - 12.4. NO ADVICE OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY YOU FROM GOOGLE, OR THROUGH OR FROM THE SERVICE OR CONTENT, WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED IN THE TERMS. - 12.5. GOOGLE, ITS LICENSORS AND THEIR SUPPLIERS FURTHER EXPRESSLY DISCLAIM ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - - -13. LIMITATION OF LIABILITY - 13.1. EXCEPT AS EXPRESSLY PROVIDED IN THE INDEMNITY PROVISION (SECTION 14) AND SUBJECT TO SECTION 12.1, YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND GOOGLE?S LICENSORS AND THEIR SUPPLIERS, WILL NOT BE LIABLE TO YOU FOR: - a. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, HOWEVER CAUSED AND UNDER ANY THEORY OF LIABILITY (INCLUDING, BUT NOT BE LIMITED TO, ANY LOSS OF PROFIT (WHETHER INCURRED DIRECTLY OR INDIRECTLY), ANY LOSS OF GOODWILL OR BUSINESS REPUTATION, ANY LOSS OF DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR OTHER INTANGIBLE LOSS); - b. ANY LOSS OR DAMAGE AS A RESULT OF: - i. ANY RELIANCE PLACED BY YOU ON THE COMPLETENESS, ACCURACY OR EXISTENCE OF ANY ADVERTISING, OR AS A RESULT OF ANY RELATIONSHIP OR TRANSACTION BETWEEN YOU AND ANY ADVERTISER OR SPONSOR WHOSE ADVERTISING APPEARS ON THE SERVICES; - ii. ANY CHANGES THAT GOOGLE MAY MAKE TO THE SERVICES, OR ANY PERMANENT OR TEMPORARY CESSATION IN THE PROVISION OF THE SERVICES (OR ANY FEATURES WITHIN THE SERVICES); - iii. THE DELETION OF, CORRUPTION OF, OR FAILURE TO STORE, ANY CONTENT AND OTHER COMMUNICATIONS DATA MAINTAINED OR TRANSMITTED BY OR THROUGH YOUR USE OF THE SERVICES; - iv. YOUR FAILURE TO PROVIDE GOOGLE WITH ACCURATE ACCOUNT INFORMATION; OR - v. YOUR FAILURE TO KEEP YOUR PASSWORD OR ACCOUNT DETAILS SECURE AND CONFIDENTIAL. - 13.2. THE LIMITATIONS ON GOOGLE'S LIABILITY TO YOU IN SECTION 13.1 ABOVE WILL APPLY WHETHER OR NOT GOOGLE, ITS AFFILIATES, LICENSORS OR THEIR SUPPLIERS HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES OR DAMAGES. - - -14. Indemnity - 14.1. You hereby agree to indemnify, defend and hold Google, its strategic partners, officers, directors, agents, affiliates, licensors and their suppliers ("the Indemnified Parties") harmless from and against any claim or liability arising out of: (a) your use of the Maps APIs in breach of the Terms or applicable policies; (b) your Maps API Implementation; (c) any use by users of your Maps API Implementation; (d) any breach of or noncompliance with any representation, warranty or obligation in these Terms or applicable policies; and (e) any claim that your Maps API Implementation or Your Content violates any applicable law, including but not limited to any claim that your Maps API Implementation infringes the rights of a third party. You will cooperate as fully as reasonably required in the defense of any claim. Google reserves the right, at its own expense, to assume the exclusive defense and control of any matter subject to indemnification by you. You acknowledge that damages for improper use of the Maps APIs may be irreparable; therefore, Google is entitled to seek equitable relief, including but not limited to preliminary injunction and injunction, in addition to all other remedies. - - -15. Copyright Policies - 15.1. It is Google's policy to respond to notices of alleged copyright infringement that comply with applicable international intellectual property law (including, in the United States, the Digital Millennium Copyright Act) and to terminate the accounts of repeat infringers. Details of Google's policy can be found at http://www.google.com/igoogle_dmca.html. - - -16. Other Content - 16.1. The Service may include hyperlinks to other web sites or content or resources. Google has no control over any web sites or resources that are provided by companies or persons other than Google. You acknowledge and agree that Google is not responsible for the availability of any such external sites or resources, and does not endorse any advertising, products or other materials on or available from such web sites or resources. - 16.2. You acknowledge and agree that Google is not liable for any loss or damage that may be incurred by you as a result of the availability of those external sites or resources, or as a result of any reliance placed by you on the completeness, accuracy or existence of any advertising, products, or other materials on, or available from, such web sites or resources. - - -17. Language of the Terms - 17.1. Where Google has provided you with a translation of the English language version of the Terms, you agree that the translation is provided for your convenience only and that the English language version of the Terms will govern your relationship with Google. - 17.2. If there is any contradiction between the English language version of the Terms and a translation of the Terms, the English language version will take precedence. - - -18. General Legal Terms - 18.1. The Terms constitute the whole legal agreement between you and Google and govern your use of the Service and Content, and completely replace and supersede any prior agreements between you and Google, written or oral, in relation to the Service and Content. The Terms may be assigned by Google and will inure to the benefit of Google, its successors and assigns. - 18.2. You agree that Google may provide you with notices, including those regarding changes to the Terms, by email, regular mail, or postings on the Service. - 18.3. You agree that if Google does not exercise or enforce any legal right or remedy contained in the Terms (or that Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google. Any waiver of any provision of these Terms will be effective only if Google expressly states in a signed writing that it is waiving a specified Term. - 18.4. If any court of law that has jurisdiction rules that any provision of these Terms is invalid, then that provision will be removed from the Terms without affecting the rest of the Terms. The remaining provisions of the Terms will continue to be valid and enforceable. - 18.5. You acknowledge and agree that each member of the group of companies of which Google is the parent will be third party beneficiaries to the Terms and that such other companies will be entitled to directly enforce, and rely upon, any provision of the Terms that confers a benefit on (or rights in favor of) them. Other than this, no other person or company will be a third party beneficiary to the Terms. - 18.6. The Terms, and your relationship with Google under the Terms, will be governed by the laws of the State of California, USA, without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located in the County of Santa Clara, California, USA, to resolve any legal matter arising from the Terms. Notwithstanding this, you agree that Google will be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction. -</textarea> -</div> - -<form action="signup.html" method="get" onsubmit="return CheckForm(this)"> - <div class="terms"> - <table style="width:95%"> - <tr> - <td style="width:1em"><input type="checkbox" name="agreeTerms" value="1"/></td> - <td>I have read and agree with the terms and conditions <span class="printable">(<a href="maps-api-tos.pdf">printable version</a>)</span></td> - </tr> - <tr> - <td></td> - <td> - My certificate's MD5 fingerprint: - <input type="text" name="fp" size="47" value=""/> - </td> - </tr> - <tr> - <td></td> - <td><input type="submit" value="Generate API Key"/></td> - </tr> - </table> - </div> -</form> - - <!-- end body text --> - - - </div><!-- end gc-pagecontent --> - </div><!-- end gooey wrapper --> - - </div> <!-- end codesite content --> - -<div id="gc-footer" dir="ltr"> - <div class="text"> - - ©2008 Google - - <a href="/">Code Home</a> - - <a href="http://www.google.com/accounts/TOS">Site Terms of Service</a> - - <a href="http://www.google.com/privacy.html">Privacy Policy</a> - - <a href="/more/">Site Directory</a> - <br /> - <br /> - <!-- end gc-footer --> - </div> -</div><!-- end gc-containter --> - </body> -</html> - diff --git a/docs/html/maps-api-tos.pdf b/docs/html/maps-api-tos.pdf Binary files differdeleted file mode 100644 index 80c2836..0000000 --- a/docs/html/maps-api-tos.pdf +++ /dev/null diff --git a/docs/html/sdk/1.5_r1/index.jd b/docs/html/sdk/1.5_r1/index.jd index 412887a..834ab79 100644 --- a/docs/html/sdk/1.5_r1/index.jd +++ b/docs/html/sdk/1.5_r1/index.jd @@ -2,51 +2,72 @@ sdk.version=1.5 sdk.rel.id=1 sdk.date=April 2009 -sdk.win_download= +sdk.win_download=android-sdk-windows-1.5_r1.zip sdk.win_bytes= sdk.win_checksum= -sdk.mac_download= +sdk.mac_download=android-sdk-mac_x86-1.5_r1.zip sdk.mac_bytes= sdk.mac_checksum= -sdk.linux_download= +sdk.linux_download=android-sdk-linux_x86-1.5_r1.zip sdk.linux_bytes= sdk.linux_checksum= -page.title=Download Android SDK +page.title=Android 1.5 SDK, Release 1 @jd:body <h2>SDK Contents</h2> <h4>Development tools</h4> -<p>The SDK includes a variety of tools for developing and debugging application code and designing an application UI. You can read about the tools in the +<p>The SDK includes a full set of tools for developing and debugging application code and designing an application UI. You can read about the tools in the <a href="{@docRoot}guide/developing/tools/index.html">Dev Guide</a> and access them in the <code><sdk>/tools/</code> directory. -<p>The tools package included in this SDK includes many updates from that provided in the previous SDK and requires you to migrate your applications to the new development environment. For details, see the <a href="upgrading">Upgrading the SDK</a> document.</p> +<p>The tools package in this SDK includes updates from those provided in the previous SDK. The tools also require a different project structure. To use the new tools, you need to migrate your applications to the new development environment. For more information about how to migrate, see <a href="{@docRoot}sdk/1.5_r1/upgrading.html">Upgrading the SDK</a>. -<h4 id="system_images">System Images</h4> +<p>For more information about the new tools features, see the <a href="{@docRoot}sdk/RELEASENOTES.html">SDK Release Notes</a>. -<p>The Android system images listed below are included in this SDK. For more information about a system image — features, applications included, localizations, API changes, and so on — see its Version Notes. </p> +<h4 id="system_images">Android Platforms</h4> + +<p>This SDK includes multiple Android platform versions that you use to develop applications. For each version, both a fully compliant Android library and system image are provided. The table below lists the platform versions included in this SDK. For more information about a platform version — features, applications included, localizations, API changes, and so on — see its Version Notes. </p> <table style="margin-right:1em;" width="80%"> <tr> -<th><nobr>System Image</nobr></th><th><nobr>API Level</nobr></th><th>Notes</th><th>Description</th> +<th><nobr>Platform</nobr></th><th><nobr>API Level</nobr></th><th>Notes</th><th>Description</th> </tr> <tr> <td width="5%"><nobr>Android 1.5</nobr></td> <td width="5%">3</td> <td width="5%"><nobr><a href="{@docRoot}sdk/android-1.5.html">Version Notes</a></nobr></td> -<td>Includes a set of standard development applications. </td> +<td>Includes a standard Android 1.5 library and system image with a set of development applications. Does not include any external libraries (such as the Maps external library).</td> </tr> <tr> <td width="5%"><nobr>Android 1.1</nobr></td> <td width="5%">2</td> <td width="5%"><nobr><a href="{@docRoot}sdk/android-1.1.html">Version Notes</a></nobr></td> -<td>Includes a set of standard development applications. </td> +<td>Includes a compliant Android 1.1 library and system image with a set of development applications. Also includes the Maps external library (due to legacy build system issues).</a> +external library. </td> + +</tr> +</table> + +<h4 id="system_images">SDK Add-Ons</h4> + +<p>An SDK add-on provides a development environment for an Android external library or a customized (but fully compliant) Android system image. This SDK includes the SDK add-on listed below. The Android system API Level required by the add-on is noted.</p> +<table style="margin-right:1em;" width="80%"> +<tr> +<th><nobr>Add-On</nobr></th><th><nobr>API Level</nobr></th><th>Notes</th><th>Description</th> +</tr> +<tr> +<td width="5%"><nobr>Google APIs</nobr></td> +<td width="5%">3</td> +<td width="5%"> </td> +<td>Includes the com.google.android.maps external library, a compliant +system image, a {@link android.location.Geocoder Geocoder} +backend service implementation, documentation, and sample code. </td> </tr> </table> @@ -55,7 +76,6 @@ page.title=Download Android SDK <p>You can look at a variety of tutorials and samples in the <a href="{@docRoot}guide/samples/index.html">Dev Guide</a> and access the sample code itself in the <code><sdk>/platforms/android-1.5/samples/</code> directory of the SDK package. Note the new location — the SDK now includes multiple platform versions that you can develop against and each has its own sample code directory. </p> -<!-- <h4>Documentation</h4> <p>The SDK package includes a full set of local documentation. To view it, open the <code><sdk>/documentation.html</code> file in a web browser. If you are developing in an IDE such as Eclipse, you can also view the reference documentation directly in the IDE. </p> @@ -63,5 +83,4 @@ in the <code><sdk>/platforms/android-1.5/samples/</code> directory of the <p>The most current documentation is always available on the Android Developers site:</p> <p style="margin-left:2em;"><a href="http://developer.android.com/index.html">http://developer.android.com/</a></p> ---> diff --git a/docs/html/sdk/1.5_r1/installing.jd b/docs/html/sdk/1.5_r1/installing.jd index a1f7cff..bd366ff 100644 --- a/docs/html/sdk/1.5_r1/installing.jd +++ b/docs/html/sdk/1.5_r1/installing.jd @@ -5,6 +5,328 @@ sdk.date=April 2009 page.title=Installing the Android SDK @jd:body -<p>See the <a href="{@docRoot}sdk/preview/index.html">Download page</a> for more information.</p> + +<p>This page describes how to install the Android SDK and set up your +development environment. If you haven't downloaded the SDK, you can +do so from the +<a href="{@docRoot}sdk/1.5_r1/index.html">Download</a> page. Once you've downloaded +the SDK, return here.</p> + +<p>If you encounter any problems during installation, see the +<a href="#installnotes">Installation Notes</a> at the bottom of +this page.</p> + +<h4 style="margin-top">Upgrading?</h4> +<p>If you have already developed applications using an earlier version +of the SDK, please read +<a href="{@docRoot}sdk/1.5_r1/upgrading.html"><strong>Upgrading the +SDK</strong></a></b>, instead. +</p> + + +<h2 id="setup">Preparing for Installation</h2> + +<p>Before you begin, take a moment to confirm that your development machine meets the +<a href="{@docRoot}sdk/1.5_r1/requirements.html">System Requirements</a>. +</p> + +<p>If you will be developing on Eclipse with the Android Development +Tools (ADT) Plugin — the recommended path if you are new to +Android — make sure that you have a suitable version of Eclipse +installed on your computer (3.3 or newer). If you need to install Eclipse, you can +download it from this location: </p> + +<p style="margin-left:2em;"><a href= +"http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a +></p> + +<p>A Java or RCP version of Eclipse is recommended. </p> + +<h2 id="installingsdk">Installing the SDK</h2> + +<p>After downloading the SDK, unpack the .zip archive to a suitable location on your machine. +By default, the SDK files are unpacked into a directory named +<code>android_sdk_<em><platform</em>>_<em><release></em></code>. +The directory contains a local copy of the documentation (accessible by opening +<code>documentation.html</code> in your browser) and the subdirectories +<code>tools/</code>, <code>add-ons/</code>, <code>platforms/</code>, and others. Inside +each subdirectory of <code>platforms/</code> you'll find <code>samples/</code>, which includes +code samples that are specific to each version of the platform.</p> + +<p>Make a note of the name and location of the unpacked SDK directory on your system — you +will need to refer to the SDK directory later, when setting up the Android plugin or when +using the SDK tools.</p> + +<p>Optionally, you may want to add the location of the SDK's primary <code>tools</code> directory +to your system PATH. The primary <code>tools/</code> directory is located at the root of the +SDK folder. Adding <code>tools</code> to your path lets you run Android Debug Bridge (adb) and +the other command line <a href="{@docRoot}guide/developing/tools/index.html">tools</a> without +needing to supply the full path to the tools directory. </p> +<ul> + <li>On Linux, edit your <code>~/.bash_profile</code> or <code>~/.bashrc</code> file. Look + for a line that sets the PATH environment variable and add the + full path to the <code>tools/</code> directory to it. If you don't + see a line setting the path, you can add one:</li> + + <ul><code>export PATH=${PATH}:<em><your_sdk_dir></em>/tools</code></ul> + + <li>On a Mac, look in your home directory for <code>.bash_profile</code> and + proceed as for Linux. You can create the <code>.bash_profile</code> if + you haven't already set one up on your machine. </li> + + <li>On Windows, right-click on My Computer, and select Properties. + Under the Advanced tab, hit the Environment Variables button, and in the + dialog that comes up, double-click on Path (under System Variables). Add the full path to the + <code>tools/</code> directory to the path. </li> + </ul> + +<p>Note that, if you update your SDK in the future, you +should remember to update your PATH settings to point to the new location, if different.</p> + +<p>If you will be using the Eclipse IDE as your development environment, +the next section describes how to install the Android Development Tools plugin and set up Eclipse. +If you choose not to use Eclipse, you can +develop Android applications in an IDE of your choice and then compile, debug and deploy using +the tools included in the SDK (skip to <a href="#next">Next Steps</a>).</p> + + +<h2 id="installingplugin">Installing the ADT Plugin for Eclipse</h2> + +<p>Android offers a custom plugin for the Eclipse IDE, called Android +Development Tools (ADT), that is designed to give you a powerful, +integrated environment in which to build Android applications. It +extends the capabilites of Eclipse to let you quickly set up new Android +projects, create an application UI, add components based on the Android +Framework API, debug your applications using the Android SDK tools, and even export +signed (or unsigned) APKs in order to distribute your application.</p> + +<p>In general, using Eclipse with ADT is a highly recommended +approach to Android development and is the fastest way to get started. +(If you prefer to work in an IDE other than Eclipse, +you do not need to install Eclipse or ADT, instead, you can directly +use the SDK tools to build and debug your application.)</p> + +<p>Once you have Eclipse installed, as described in <a href="#setup">Preparing for +Installation</a>, follow the steps below to +download the ADT plugin and install it in your respective Eclipse +environment. </p> + +<table style="font-size:100%"> +<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr> +<tr> +<td width="45%"> +<!-- 3.3 steps --> +<ol> + <li>Start Eclipse, then select <strong>Help</strong> > <strong>Software Updates</strong> +> <strong>Find and Install...</strong>. </li> + <li>In the dialog that appears, select <strong>Search for new features to install</strong> +and click <strong>Next</strong>. </li> + <li>Click <strong>New Remote Site</strong>. </li> + <li>In the resulting dialog box, enter a name for the remote site (e.g. "Android Plugin") and + enter the URL: + <pre>https://dl-ssl.google.com/android/eclipse/</pre> + <p>If you have trouble aqcuiring the plugin, try using "http" in the URL, + instead of "https" (https is preferred for security reasons).</p> + <p>Click <strong>OK</strong>.</p> </li> + <li>You should now see the new site added to the search list (and checked). + Click <strong>Finish</strong>. </li> + <li>In the subsequent Search Results dialog box, select the checkbox for the + <strong>Android Plugin</strong>. + This will select the nested tools: "Android DDMS" and "Android Developer Tools". + Click <strong>Next</strong>.</li> + <li>Read and accept the license agreement, then click <strong>Next</strong>. </li> + <li>On the following Installation window, click <strong>Finish</strong>. </li> + <li>The ADT plugin is not digitally signed. Accept the installation anyway + by clicking <strong>Install All</strong>. </li> + <li>Restart Eclipse. </li> +</ol> + +</td> +<td> + +<!-- 3.4 steps --> +<ol> + <li>Start Eclipse, then select <strong>Help</strong> > <strong>Software Updates...</strong>.</li> + <li>In the dialog that appears, click the <strong>Available Software</strong> tab. </li> + <li>Click <strong>Add Site...</strong> </li> + <li>Enter the Location: + <pre>https://dl-ssl.google.com/android/eclipse/</pre> + <p>If you have trouble aqcuiring the plugin, try using "http" in the Location URL, + instead of "https" (https is preferred for security reasons).</p> + <p>Click <strong>OK</strong>.</p></li> + <li>Back in the Available Software view, you should see the plugin listed by the URL, + with "Developer Tools" nested within it. Select the checkbox next to + Developer Tools and click <strong>Install...</strong></li> + <li>On the subsequent Install window, "Android DDMS" and "Android Developer Tools" + should both be checked. Click <strong>Next</strong>. </li> + <li>Read and accept the license agreement, then click <strong>Finish</strong>.</li> + <li>Restart Eclipse. </li> +</ol> + +</td> +</tr> +</table> + +<p>Now modify your Eclipse preferences to point to the Android SDK directory:</p> +<ol> + <li>Select <strong>Window</strong> > <strong>Preferences...</strong> to open the Preferences + panel (Mac: <strong>Eclipse</strong> > <strong>Preferences</strong>).</li> + <li>Select <strong>Android</strong> from the left panel. </li> + <li>For the <em>SDK Location</em> in the main panel, click <strong>Browse...</strong> and +locate your downloaded SDK directory. </li> + <li>Click <strong>Apply</strong>, then <strong>OK</strong>.</li> +</ol> + +<p>Done! If you haven't encountered any problems, then you're ready to +begin developing Android applications. See the +<a href="#next">Next Steps</a> section for suggestions on how to start. </p> + + +<h3 id="troubleshooting">Troubleshooting ADT Installation</h3> +<p> +If you are having trouble downloading the ADT plugin after following the steps above, here are +some suggestions: </p> + +<ul> + <li>If Eclipse can not find the remote update site containing the ADT plugin, try changing + the remote site URL to use http, rather than https. That is, set the Location for the remote site to: + <pre>http://dl-ssl.google.com/android/eclipse/</pre></li> + <li>If you are behind a firewall (such as a corporate firewall), make + sure that you have properly configured your proxy settings in Eclipse. + In Eclipse 3.3/3.4, you can configure proxy information from the main + Eclipse menu in <strong>Window</strong> (on Mac, <strong>Eclipse</strong>) > + <strong>Preferences</strong> > <strong>General</strong> > + <strong>Network Connections</strong>.</li> +</ul> +<p> +If you are still unable to use Eclipse to download the ADT plugin as a remote update site, you +can download the ADT zip file to your local machine and manually install the it: +</p> +<ol> + <li><a href="{@docRoot}sdk/adt_download.html">Download the ADT zip file</a> (do not unpack it).</li> + <li>Follow steps 1 and 2 in the default install instructions (above).</li> + <li>In Eclipse 3.3, click <strong>New Archive Site...</strong>. <br/> + In Eclipse 3.4, click <strong>Add Site...</strong>, then <strong>Archive...</strong></li> + <li>Browse and select the downloaded zip file.</li> + <li>Follow the remaining procedures, above, starting from steps 5.</li> +</ol> +<p>To update your plugin once you've installed using the zip file, you will have to +follow these steps again instead of the default update instructions.</p> + +<h4>Other install errors</h4> + +<p>Note that there are features of ADT that require some optional +Eclipse components (for example, WST). If you encounter an error when +installing ADT, your Eclipse installion might not include these components. +For information about how to quickly add the necessary components to your +Eclipse installation, see the troubleshooting topic +<a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT +Installation Error: "requires plug-in org.eclipse.wst.sse.ui"</a>.</p> + +<h4>For Linux users</h4> +<p>If you encounter this error when installing the ADT Plugin for Eclipse: +<pre> +An error occurred during provisioning. +Cannot connect to keystore. +JKS</pre> +<p> +...then your development machine lacks a suitable Java VM. Installing Sun +Java 6 will resolve this issue and you can then reinstall the ADT +Plugin.</p> + + +<h2 id="next">Next Steps</h2> +<p>Once you have completed installation, you are ready to +begin developing applications. Here are a few ways you can get started: </p> + +<p><strong>Learn about Android</strong></p> +<ul> + <li>Take a look at the <a href="{@docRoot}guide/index.html">Dev + Guide</a> and the types of information it provides</li> + <li>Read an introduction to Android as a platform in <a + href="{@docRoot}guide/basics/what-is-android.html">What is + Android?</a></li> + <li>Learn about the Android framework and how applications run on it in + <a href="{@docRoot}guide/topics/fundamentals.html">Application + Fundamentals</a></li> + <li>Take a look at the Android framework API specification in the <a + href="{@docRoot}reference/index.html">Reference</a> tab</li> +</ul> + +<p><strong>Explore the SDK</strong></p> +<ul> + <li>Get an overview of the <a + href="{@docRoot}guide/developming/tools/index.html">development + tools</a> that are available to you</li> + <li>Read how to develop <a + href="{@docRoot}guide/developing/eclipse-adt.html">in Eclipse/ADT</a> or + <a href="{@docRoot}guide/developing/other-ide.html">in other IDEs</a> + </li> +</ul> + +<p><strong>Explore some code</strong></p> +<ul> + <li>Set up a <a href="{@docRoot}guide/tutorials/hello-world.html">Hello + World application</a> (highly recommended, especially for Eclipse users)</li> + <li>Follow the <a href="{@docRoot}guide/tutorials/notepad/index.html"> + Notepad Tutorial</a> to build a full Android application </li> + <li>Create a new project for one of the other sample applications + included in <code><em><sdk></em>/platforms/<em><platfrom></em>/samples</code>, + then compile and run it in your development environment</li> +</ul> + +<p><strong>Visit the Android developer groups</strong></p> +<ul> + <li>Take a look at the <a + href="{@docRoot}community/index.html">Community</a> tab to see a list of + Android developers groups. In particular, you might want to look at the + <a href="http://groups.google.com/group/android-developers">Android + Developers</a> group to get a sense for what the Android developer + community is like.</li> +</ul> + + +<h2 id="installnotes">Installation Notes</h2> + +<h3>Ubuntu Linux Notes</h3> + +<ul> + <li>If you need help installing and configuring Java on your + development machine, you might find these resources helpful: + <ul> + <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/Java </a></li> + <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/JavaInstallation</a></li> + </ul> + </li> + <li>Here are the steps to install Java and Eclipse, prior to installing + the Android SDK and ADT Plugin. + <ol> + <li>If you are running a 64-bit distribution on your development + machine, you need to install the <code>ia32-libs</code> package using + <code>apt-get:</code>: + <pre>apt-get install ia32-libs</pre> + </li> + <li>Next, install Java: <pre>apt-get install sun-java6-bin</pre></li> + <li>The Ubuntu package manager does not currently offer an Eclipse 3.3 + version for download, so we recommend that you download Eclipse from + eclipse.org (<a + href="http://www.eclipse.org/downloads/">http://www.eclipse.org/ + downloads/</a>). A Java or RCP version of Eclipse is recommended.</li> + <li>Follow the steps given in previous sections to install the SDK + and the ADT plugin. </li> + </ol> + </li> +</ul> + +<h3>Other Linux Notes</h3> + +<ul> + <li>If JDK is already installed on your development computer, please + take a moment to make sure that it meets the version requirements listed + in the <a href="{@docRoot}sdk/1.1_r1/requirements.html">System Requirements</a>. + In particular, note that some Linux distributions may include JDK 1.4 or Gnu + Compiler for Java, both of which are not supported for Android development.</li> +</ul> + diff --git a/docs/html/sdk/1.5_r1/upgrading.jd b/docs/html/sdk/1.5_r1/upgrading.jd index 5323131..0b7312b 100644 --- a/docs/html/sdk/1.5_r1/upgrading.jd +++ b/docs/html/sdk/1.5_r1/upgrading.jd @@ -2,175 +2,351 @@ page.title=Upgrading the SDK sdk.version=1.5_r1 @jd:body -<!-- -<div class="sidebox-wrapper"> - <div class="sidebox-inner"> - <h2>Useful Links</h2> +<div id="qv-wrapper"> +<div id="qv"> + + <h2>Upgrading quickview</h2> + <ul> + <li>The Android 1.5 SDK uses a new project structure and a new ADT plugin (ADT 0.9). </li> + <li>To move existing projects into the SDK, you must make some minor changes in your + development environment.</li> + <li>The new ADT plugin (ADT 0.9) <em>is not compatible</em> with projects created in previous SDKs.</li> + <li>You need to uninstall your existing ADT plugin, before installing ADT 0.9.</li> + </ul> + + <h2>In this document</h2> + <ol> + <li><a href="#Install">Install the SDK</a></li> + <li><a href="#UpdateAdt">Update Your Eclipse ADT Plugin</a></li> + <li><a href="#UpdateYourProjects">Update Your Projects</a> + <ol> + <li><a href="#EclipseUsers">Eclipse Users</a></li> + <li><a href="#AntUsers">Ant Users</a></li> + </ol> + </li> + <li><a href="#MigrateYourApplications">Migrate Your Applications</a></li> + </ol> + + <h2>Migrating references</h2> + <ol> + <li><a href="{@docRoot}sdk/api_diff/3/changes.html">Android 1.5 API Differences</a></li> + <!-- <li><a href="">TODO: LINK TO DAN'S POST »</a></li> --> + <li><a +href="http://android-developers.blogspot.com/2009/04/ui-framework-changes-in-android-15.html">UI +framework changes in Android 1.5 »</a></li> + </ol> - <ul class="noindent"> - <li><a href="migrating/0.9-1.0/changes-overview.html">Overview of Changes</a> - <p>A high-level look at what's changed in Android, with - discussion of how the changes may affect your apps.</p></li> - - <li><a href="migrating/0.9-1.0/changes.html">API Diff Report</a> - <p>A detailed report that lists all the specific changes in the latest SDK.</p></li> - - <li><a href="RELEASENOTES.html">Release Notes</a> - <p>Version details, known issues, and resolved issues. </p></li> - - <li><a href="http://groups.google.com/group/android-developers">Android Developers Group</a> - <p>A forum where you can discuss migration issues and learn from other Android developers. </p></li> - - <li><a href="http://code.google.com/p/android/issues/list">Android Issue Tracker</a> - <p>If you think you may have found a bug, use the issue tracker to report it.</p></li> - </ul> - - </div> </div> ---> +</div> +<p>This document describes how to move your development environment and existing +Android applications from an Android 1.0 or 1.1 SDK to the Android 1.5 SDK. +If you are migrating applications from an SDK older than 1.0, please also read the upgrading +document available in the Android 1.0 SDK package.</p> - <div id="qv-wrapper"> - <div id="qv"> +<p>There are several compelling reasons to upgrade, such as new SDK tools +that make developing more efficient and new APIs that allow you to expand the feature-set +of your applications. However, even if you or your applications don't require these enhancements, +it's important that you upgrade to ensure that your applications run properly on the +Android 1.5 platform.</p> -<h2>Upgrading quickview</h2> -<ul> -<li>The Android 1.5 SDK uses a new project structure and a new ADT plugin (ADT 0.9). </li> -<li>To move existing projects into the SDK, you must make some minor changes in your development environment.</li> -<li>The new ADT plugin (ADT 0.9) <em>is not compatible</em> with projects created in previous SDKs.</li> -<li>You need to uninstall your existing ADT plugin, before installing ADT 0.9.</li> +<p>The Android 1.5 platform will soon be deployable to devices around the world. +If you have already released Android applications to the public, you should +test the forward-compatibility of your applications on the latest version of the platform +as soon as possible. It's unlikely that you'll encounter breakage in your applications, but +in the interest of maintaining the best user experience, you should take no risks. +So, please install the new Android SDK and test your applications on Android 1.5.</p> -</ul> +<p>For more information on new SDK features and system changes, +see the <a href="{@docRoot}sdk/android-1.5.html">Android 1.5 Version Notes</a>.</p> -<!--<h2>Related Information</h2> -<ol> -<li><a href="{@docRoot}sdk/api_diff/3/changes.html">Android 1.5 API Differences</a></li> -</ol> ---> -</div> -</div> -<p>See the <a href="{@docRoot}sdk/preview/index.html">Download page</a> for more information.</p> +<h2 id="Install">Install the SDK</h2> -<!-- <p>This document describes how to move your development environment and existing -Android applications from an Android 1.1 or 1.0 SDK to the Android 1.5 SDK. -If you are migrating applications from an earlier SDK, please read the upgrading -document available in the Android 1.0 SDK package. -</p> +<p>If you haven't yet downloaded the SDK, <a href="{@docRoot}sdk/1.5_r1/index.html">download from here</a> +and unpack it into a safe location.</p> -<p>To ensure that your existing applications run properly with the Android 1.5 system available -on mobile devices, you need to install the Android 1.5 SDK and port your existing Android -applications to it. The sections below will guide you through the process.</p> +<p><strong>Before you begin:</strong> +If you had previously setup your PATH variable to point to the SDK tools directory, +then you need to update it to point to the new SDK. For example, for a +<code>.bashrc</code> or <code>.bash_profile</code> file:</p> +<pre>export PATH=$PATH:<em><your_sdk_dir></em>/tools</pre> -</ul> +<p>If you don't use Eclipse for development, +skip to <a href="#updateYourProjects">Update Your Projects</a>.</p> -<h2 id="install-new">Installing the SDK</h2> -<p><a href="{@docRoot}sdk/1.5_r1/index.html">Download the SDK</a> and unpack it into a safe location.</p> +<h2 id="UpdateAdt">Update Your Eclipse ADT Plugin</h2> -<p>After unpacking the new SDK and saving it an appropriate location, you should:</p> +<p><em>If you installed ADT-0.9_pre with the early look 1.5 SDK, there have been +additional changes, so please continue with this guide and update to the final ADT 0.9.</em></p> -<ul> - <li>Wipe your emulator data. <p>Some data formats have changed since the last - SDK release, so any previously saved data in your emulator must be removed. Open a console/terminal - and navigate to the <code>/tools</code> directory of your new SDK. Launch the - emulator with the <code>-wipe-data</code> option. - <p>Windows: <code>emulator -wipe-data</code><br/> - Mac/Linux: <code>./emulator -wipe-data</code></p> - </li> - <li>Update your PATH variable (Mac/Linux; optional). <p>If you had previously setup your - PATH variable to point to the SDK tools directory, then you'll need to update it to - point to the new SDK. For example, for a <code>.bashrc</code> or <code>.bash_profile</code> file: - <code>export PATH=$PATH:<em><your_new_sdk_dir></em>/tools</code></p> - </li> - <li>If (and only if) you are developing using Ant, you will also need to modify - your build.xml properties to point to the new SDK. - <p>Open the <code>default.properties</code> file associated with your build.xml - file (typically located in the same directory). In the default.properties - file, update the <code>sdk-folder</code> property with the full path to - the new SDK directory.</p></li> -</ul> +<p>A new ADT plugin (version 0.9) is required for the Android 1.5 SDK. +Because the component structure has been changed since Android 1.1, +the Android 1.5 SDK does not work with ADT 0.8 (or older) and previously installed SDKs will not +work with ADT 0.9. However, the Android 1.5 SDK includes an Android 1.1 SDK image that you +can build against while using ADT 0.9. </p> -<a name="Updating_the_ADT_plugin" id="Updating_the_ADT_plugin"></a> -<h2 id="update-plugin">Update your ADT Eclipse Plugin</h2> +<p class="note">For information about using different system images (such as Android 1.1) +while running this SDK, see Developing <a href="{@docRoot}guide/developing/eclipse-adt.html"> +In Eclipse, with ADT</a> or <a href="{@docRoot}guide/developing/other-ide.html">In +Other IDEs</a>, as appropriate for your development environment.</p> -<p>If you develop on Eclipse and are migrating from an Android 1.0 -SDK, no update of the ADT plugin is needed — skip to <a href="#updateEclipsePrefs">Update your Eclipse SDK Preferences</a>. </p> +<p>In order to upgrade your Eclipse IDE to use the new 0.9 ADT, follow the steps below +for your respective version of Eclipse.</p> -<p>If you are migrating from an earlier version of the SDK, you will -need to update the ADT plugin. <p>You may also want to upgrade your -ADT plugin when a new version becomes available for your existing version -of the SDK.</p> +<h3 id="uninstallAdt">Uninstall your previous ADT plugin</h3> -<p>The steps below describe how to update the ADT plugin to the latest -version available. </p> +<p>You must uninstall your existing ADT plugin (0.8 or older). If you do not uninstall it, +you will get a conflict with the Android Editors when installing the new ADT. +(If you have already installed ADT-0.9_pre with the early look 1.5 SDK, you can skip this +uninstall procedure and continue to <a href="#installAdt">Install the 0.9 ADT plugin</a>).</p> <table style="font-size:100%"> <tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr> <tr> <td width="50%"> +<!-- 3.3 steps --> <ol> - <li> Select <strong>Help</strong> > <strong>Software Updates</strong> > <strong>Find and Install...</strong>. </li> - <li> Select <strong>Search for updates of the currently installed features</strong> and click <strong>Finish</strong>. </li> - <li> If any update for ADT is available, select and install. </li> - <li> Restart Eclipse.</li> + <li>Select <strong>Help</strong> > <strong>Software Updates</strong> > + <strong>Manage Configuration</strong>. </li> + <li>Expand the list in the left panel to reveal the installed tools.</li> + <li>Right-click "Android Editors" and click <strong>Uninstall</strong>. Click <strong>OK</strong> + to confirm.</li> + <li>Restart Eclipse. + <p>(Do not uninstall "Android Development Tools".)</p></li> </ol> -<p> Alternatively, </p> +</td> +<td> +<!-- 3.4 steps --> <ol> - <li> Select <strong>Help</strong> > <strong>Software Updates</strong> > <strong>Manage Configuration</strong>. </li> + <li>Select <strong>Help</strong> > <strong>Software Updates</strong>.</li> + <li>Select the <strong>Installed Software</strong> tab.</li> + <li>Select "Android Editors". Click <strong>Uninstall</strong>.</li> + <li>In the next window, be sure "Android Editors" is checked, then click <strong>Finish</strong> + to uninstall.</li> + <li>Restart Eclipse. + <p>(Do not uninstall "Android Development Tools".)</p></li> +</ol> +</td> +</tr> +</table> + + +<h3 id="installAdt">Install the 0.9 ADT plugin</h3> - <li> Navigate down the tree and select <strong>Android Development Tools <version></strong> </li> - <li> Select <strong>Scan for Updates</strong> under <strong>Available Tasks</strong>.</li> +<p>Only install the new plugin once you've completed the procedure to +<a href="#uninstallAdt">Uninstall your previous ADT plugin</a>.</p> + +<table style="font-size:100%"> +<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr> +<tr> +<td width="50%"> +<!-- 3.3 steps --> +<ol> + <li>Select <strong>Help</strong> > <strong>Software Updates</strong> > + <strong>Find and Install</strong>. </li> + <li>Select <strong>Search for new features to install</strong>.</li> + <li>Select the Android plugin entry by checking the box next to it, + then click <strong>Finish</strong>. + <p>(Your original entry for the plugin should still be here. If not, see the guide + to <a href="{docRoot}sdk/1.5_r1/installing.html#installingplugin">Installing the ADT Plugin</a>.) + </p></li> + <li>In the results, be sure that "Developer Tools" is checked, then click <strong>Next</strong>.</li> + <li>Read and accept the license agreement, then click <strong>Next</strong>. + <li>In the next window, click <strong>Finish</strong> to start installation.</li> + <li>The ADT plugin is not digitally signed. Accept the installation anyway by clicking + <strong>Install All</strong>.</li> + <li>Restart Eclipse.</li> </ol> </td> <td> +<!-- 3.4 steps --> <ol> - <li>Select <strong>Help</strong> > <strong>Software Updates...</strong></li> - <li>Select the <strong>Installed Software</strong> tab.</li> - <li>Click <strong>Update...</strong></li> - <li>If an update for ADT is available, select it and click <strong>Finish</strong>.</li> + <li>Select <strong>Help</strong> > <strong>Software Updates</strong>.</li> + <li>Select the <strong>Available Software</strong> tab.</li> + <li>Expand the entry for the Andriod plugin (may be listed as the location URL) + and select "Developer Tools" by checking the box next to it, then click <strong>Install</strong>. + </li>On the next window, "Android DDMS" and "Android Developer Tools" + should both be checked. Click <strong>Next</strong>.</li> + <li>Read and accept the license agreement, then click <strong>Finish</strong>.</li> <li>Restart Eclipse.</li> </ol> </td> </tr> </table> -<h2 id="updateEclipsePrefs">Update your Eclipse SDK Preferences</h2> +<p>If you encounter problems, ensure your ADT is fully uninstalled and then +follow the guide to +<a href="{@docRoot}sdk/1.5_r1/installing.html#installingplugin">Installing the ADT Plugin +for Eclipse</a>.</p> + +<h3 id="updateEclipsePrefs">Update your Eclipse SDK Preferences</h3> <p>The last step is to update your Eclipse preferences to point to the new SDK directory:</p> <ol> - <li>Select <strong>Window</strong> > <strong>Preferences...</strong> to open the Preferences panel. (Mac OSX: <strong>Eclipse</strong> > <strong>Preferences</strong>)</li> + <li>Select <strong>Window</strong> > <strong>Preferences</strong> to open the Preferences + panel (Mac: <strong>Eclipse</strong> > <strong>Preferences</strong>).</li> <li>Select <strong>Android</strong> from the left panel.</li> - <li>For the SDK Location in the main panel, click <strong>Browse...</strong> and locate the SDK directory.</li> + <li>For the <em>SDK Location</em> in the main panel, click <strong>Browse</strong> + and locate your SDK directory.</li> <li>Click <strong>Apply</strong>, then <strong>OK</strong>.</li> </ol> -<h2 id="migrate">Migrate Your Applications, if Necessary</h2> -<p>If (and only if) you have written apps in an SDK released previous to -the Android 1.0 SDK, you will need to migrate your applications. After -installing the new SDK and updating the ADT Plugin (if applicable), you -may encounter breakages in your application code, due to -framework and API changes. You'll need to update your code to match the -latest APIs.</p> +<h2 id="UpdateYourProjects">Update Your Projects</h2> + +<p>You will now need to update any and all Android projects that you have +developed using a previous version of the Android SDK.</p> + + +<h3 id="EclipseUsers">Eclipse users</h3> + +<p>If you use Eclipse to develop applications, use the following procedure to +update each project:</p> + +<ol> + <li>Right-click on the individual project (in the Package Explorer) + and select <strong>Properties</strong>.</li> + <li>In the properties, open the Android panel and select a "build target" to compile + against. This SDK offers the Android 1.1 and Android 1.5 platforms to choose from. When + you are initially updating your projects to the new SDK, we recommend that you select a build + target with the Android 1.1 platform. Click <strong>Apply</strong>, then + <strong>OK</strong>.</li> +</ol> + +<p>The new plugin creates a <code>gen/</code> folder in your project, in which it puts the +<code>R.java</code> file +and all automatically generated AIDL java files. If you get an error such as +<code>The type R is already defined</code>, +then you probably need to delete your old <code>R.java</code> or your old auto-generated +AIDL Java files in the <code>src/</code> folder. +(This <em>does not</em> apply to your own hand-crafted parcelable AIDL java files.)</p> + +<p>Note that, with the Android 1.5 SDK, there is a new process for running +applications in the Android Emulator. +Specifically, you must create an Android Virtual Device (AVD) before you can launch an instance +of the Emulator. Before attempting to run your applications with the new SDK, +please continue with the section below to +<a href="#MigrateYourApplications">Migrate Your Applications</a>.</p> + + +<h3 id="AntUsers">Ant users</h3> + +<p>If you build your projects using the Ant tool (rather than with Eclipse), note the +following changes with the new SDK tools.</p> + +<h4>build.xml has changed</h4> + +<p>You must re-create your <code>build.xml</code> file.</p> + +<p>If you had customized your <code>build.xml</code>, first make a copy of it:</p> + +<pre> +$ cd <em>my-project</em> +$ cp build.xml build.xml.old +</pre> -<p>One way to start is to open your project in Eclipse and see where the ADT -identifies errors in your application. You can also look up -specific changes in the Android APIs in the -android-1.5.html#api-changes -Android 1.5 Version Notes +<p>Now use the new <code>android</code> tool (located in <code><em>your_sdk</em>/tools/</code>) +to create a new <code>build.xml</code> that references +a specific platform target:</p> -document.</p> +<pre>$ android update project --path /path/to/my-project --target 1</pre> + +<p>The "target" corresponds to an Android platform library (including any add-ons, such as +Google APIs) that you would like to build your project against. You can view a list of available +targets (and their corresponding integer ID) with the command, <code>android list targets</code>. +When you are initially updating your projects to the new SDK, we recommend that you select the +first target ("1"), which uses the Android 1.1 platform library.</p> + +<p>A <code>gen/</code> folder will be created the first time you build and your <code>R.java</code> and +your AIDL Java files will be generated in here. You <strong>must</strong> remove +the old <code>R.java</code> and old auto-generated AIDL java files from the +<code>src/</code> folder. (This +does not apply to your own hand-crafted parcelabe AIDL java files.)</p> + +<p class="note"><strong>Note:</strong> The "activitycreator" tool has been replaced +by the new "android" tool. For information on creating new projects with the android tool, +see the documentation about <a href="{@docRoot}guide/developing/other-ide.html">Developing +In Other IDEs</a>.</p> + +<p>Note that, with the Android 1.5 SDK, there is a new process for running +applications in the Android Emulator. +Specifically, you must create an Android Virtual Device (AVD) before you can launch an instance +of the Emulator. Before attempting to run your applications with the new SDK, +please continue with the section below to +<a href="#MigrateYourApplications">Migrate Your Applications</a>.</p> + + +<h2 id="MigrateYourApplications">Migrate Your Applications</h2> + +<p>After you have completed the process above to <a href="#UpdateYourProjects">Update Your +Projects</a>, you are strongly encouraged to run each of your applications in an instance +of the emulator running the Android 1.5 system image. It's possible (however, unlikely) +that you'll encounter some breakage in your application when you run your applications on +the Android 1.5 system image. Whether you believe your application will be affected by +platform changes or not, it's very important that you test the application's +forward-compatibility on Android 1.5.</p> + +<p>To test forward-compatibility, simply run your existing application (as-is) on an Android +Emulator that's running the Android 1.5 system image. The following procedure will guide +you through the process to running your existing applications on an emulator. <em>Please read +the following guide completely before you begin</em>.</p> + +<p>To test your application on an emulator running Android 1.5:</p> +<ol> + <li><a href="#UpdateYourProjects">Update Your Project</a> (you should have done this + already, in the section above).</li> + <li>Run your existing project, as-is, on an emulator running the Android 1.5 system image. + <p>As mentioned in the guide to <a href="#UpdateYourProjects">Update Your Projects</a>, + you should have selected a "build + target" of "1", which compiles your application against the Android 1.1 system image, so there + should be no new errors in your code.</p> + <p>Eclipse users: follow the + <a href="{@docRoot}guide/developing/eclipse-adt.html#Running">Eclipse guide to + Running Your Application</a>.</p> + <p>Ant users: follow the + <a href="{@docRoot}guide/developing/other-ide.html#Running">Ant guide to + Running Your Application</a> + <p>During the procedure to Running Your Application, select a "deployment target" + for the AVD that includes the Android 1.5 platform. + If your application utilizes the Google Maps APIs (i.e., + MapView), be certain to select a target that includes the Google APIs.</p> + <p>Once you complete the procedures to run your application in your respective environment, + linked above, return here.</p> + </li> + <li>With your application running in the emulator, perform all regular testing on the application + to ensure that it functions normally (in both landscape and portrait orientations).</li> +</ol> + +<p>Chances are, your application runs just fine on the Android 1.5 platform — +new devices will be able to safely install and run your application and +current users who update their devices will be able to continue using your application as usual. +However, if something doesn't work the way you expect, then you might need to revisit +your project and make any necessary changes to your code.</p> + +<p>You can check for code breakages caused by API changes by opening your project +in Eclipse, changing the "build target" to one using the Android 1.5 platform, +and see where the ADT identifies errors in your code.</p> + +<p>There have been several API additions made for this release, but there have been +very few actual API <em>changes</em>. Only a couple (relatively unused) elements +have been removed and a few have been deprecated, so your applications written with the +Android 1.1 system library should work just fine. +Your application will be at highest risk of breakage if it uses Android APIs +that are not available in the public API documentation +or if it explicitly depends on system bugs. For information +about changes made to Android 1.5, refer to the following documents:</p> +<ul> + <li><a href="{@docRoot}sdk/api_diff/3/changes.html">Android 1.5 API Differences</a></li> + <li><a href="{@docRoot}sdk/android-1.5.html#api-changes">Android 1.5 Version Notes</a></li> + <!-- <li><a href="">TODO: LINK TO DAN'S POST ON FORWARD COMPATIBILITY »</a></li> --> + <li><a +href="http://android-developers.blogspot.com/2009/04/ui-framework-changes-in-android-15.html">UI +framework changes in Android 1.5 »</a></li> +</ul> <p>If you have additional trouble updating your code, visit the <a href="http://groups.google.com/group/android-developers">Android Developers Group</a> to seek help from other Android developers.</p> - -<p>If you have modified one of the ApiDemos applications and would like to migrate it -to the new SDK, note that you will need to uninstall the version of ApiDemos that comes -preinstalled in the emulator. For more information, or if you encounter an "reinstallation" -error when running or installing ApiDemos, see the troubleshooting topic -<a href="{@docRoot}guide/appendix/faq/troubleshooting.html#apidemosreinstall">I can't install ApiDemos -apps in my IDE because of a signing error</a> for information about how to solve the problem.</p> --->
\ No newline at end of file diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd index bad71a2..c6a887a 100644 --- a/docs/html/sdk/RELEASENOTES.jd +++ b/docs/html/sdk/RELEASENOTES.jd @@ -1,21 +1,209 @@ page.title=SDK Release Notes @jd:body -<p>This document provides version-specific information about Android SDK releases. For the latest known issues, please ensure that you're viewing this page at: <a href="http://developer.android.com/sdk/RELEASENOTES.html">http://developer.android.com/sdk/RELEASENOTES.html</a>.</p> +<p>This document provides version-specific information about Android SDK +releases. For the latest known issues, please ensure that you're viewing this +page at: +<a href="http://developer.android.com/sdk/RELEASENOTES.html">http://developer.android.com/sdk/RELEASENOTES.html</a>.</p> + +<h2 id="1.5_r1">Android 1.5 SDK, Release 1</h2> + +<p>This SDK provides updates to the development tools and Android system that +you use to create applications for compliant Android-powered devices. </p> + +<h3>Release Overview</h3> + +<p>This SDK release includes many new features for developers. Highlights of the +changes include: </p> + + <ul> + <li>Multiple versions of the Android platform are included (Android 1.1, +Android 1.5). The tools are updated to let you deploy your application +on any platform in the SDK, which helps you ensure forward-compitility and, +if applicable, backward-compatibility.</li> + <li>Introduces <a href="{@docRoot}guide/developing/tools/avd.html">Android +Virtual Devices</a> — (AVD) configurations of options that you +run in the emulator to better model actual devices. Each AVD gets its +own dedicated storage area, making it much easier to work with multiple emulators +that are running concurrently.</li> + <li>Support for SDK add-ons, which extend the +Android SDK to give you access to one or more external Android libraries and/or +a customized (but compliant) system image that can run in the emulator. </li> + <li>The new Eclipse ADT plugin (version 0.9.0) offers new Wizards to let you +create projects targetted for specific Android configurations, generate XML +resources (such as layouts, animations, and menus), generate alternate layouts, +and export and sign your application for publishing.</li> + <li>Improved JUnit support in ADT</li> + <li>Easier profiling of performance</li> + <li>Easier management of localized applications. You can now include or +exclude locale resources when building your APK from a single +Android project.</li> + <li>A new tool called "android" replaces the activitycreator script.</li> + </ul> + +<p>For details about the Android platforms included in the SDK — including +bug fixes, features, and API changes — please read the Version Notes +documents available at left. For a list of Android platforms included in this +release, see the <a href="{@docRoot}sdk/1.5_r1/index.html">Download +page</a>.</p> + +<h3>Installation and Upgrade Notes</h3> + +<p>If you've been developing an application using an Android 1.1 SDK, you need +to make a few changes to your development environment to migrate to the new SDK. +Tools and documentation are provided to assist you. No changes to the source +code of an existing application should be needed, provided that your application +is not using Android internal structures or APIs.</p> + +<p>To ensure that your existing application will work properly on a device +running the latest version of the Android platform, you are strongly encouraged +to migrate the application to the new SDK, compile it using the platform +matching the application's original API Level, and run it against the most +current platform. </p> + +<p>If you're installing the Android SDK for the first time, please see +the instructions in <a +href="{@docRoot}sdk/1.5_r1/installing.html">Installing the SDK</a>. + +<h3>SDK Add-Ons</h3> + +<p>This version of the SDK introduces support for SDK add-ons, which extend the +Android SDK to give you access to one or more external Android libraries and/or +a customized (but compliant) system image that can run in the emulator. The +purpose of an SDK add-on is to give you a way to develop applications for a +specific actual device (or family of devices) that extends the APIs available to +Android applications through external libraries or system customizations. </p> + +<p>From the perspective of your Android development environment, an SDK add-on +is similar to any of the Android platform targets included in the SDK — it +includes an external library, a system image, as well as custom emulator skins +and system properties. The add-on differs in that the Android platform it +provides may include customized UI, resources, or behaviors, a different set of +preinstalled applications, or other similar modifications. + +<p>The SDK includes a single SDK add-on — the Google APIs add-on. The +Google APIs add-on gives your application access to the com.google.android.maps +external library that is included on many (if not most) Android-powered devices. +The Google APIs add-on also includes a {@link android.location.Geocoder Geocoder} +backend service implementation. For more information, see the "Maps External +Library" section below. </p> + +<h3>Android Virtual Devices (AVDs)</h3> + +<p>The SDK now gives you the capability to compile an application against any +one of several system targets, then run it in the emulator on top of any +compatible system image. There are two types of targets:</p> +<ul> +<li>Targets that represent core Android platform versions. </li> +<li>Targets that are SDK add-ons, which typically provide application access to +one or more external libraries and/or a customized (but compliant) system image +that can run in the emulator. +</ul> + +<p>A new tool called "android" lets you discover what targets and AVDs are +available to use.</p> + +<p>For more information about AVDs, see <a +href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> + +<h3>Other Notes</h3> + +<p><strong>Maps External Library</strong></p> + +<p>In previous versions of the SDK, the com.google.android.maps package was +included in the standard Android library and system image. In the Android 1.5 +SDK, that is not the case. The Android 1.5 library and system image do not +include the Maps external library (com.google.android.maps). However, the Maps +external library is available as part of the Google APIs add-on for the Android +SDK, downloadable from this location: </p> + +<p style="margin-left:2em;"><a +href="http://code.google.com/android/add-ons/google-apis">http://code.google.com +/android/add-ons/google-apis</a> </p> + +<p>For your convenience, the Google APIs add-on is included in the SDK. </p> + +<p>For information about how to register for a Maps API Key, see +<a href="http://code.google.com/android/add-ons/google-apis/mapkey.html"> +Obtaining a Maps API Key</a>.</p> + +<p><strong>USB Drivers for Windows</strong></p> + +<p>If you are using Windows and want to develop or test your application on an +Android-powered device (such as the T-Mobile G1), you need an appropriate USB +driver. For your convenience, the Windows version of the Android SDK includes +these USB drivers that you can install, to let you develop on the device:</p> + +<ul> +<li>USB driver for 32-bit XP and Vista</li> +<li>USB driver for 64-bit Vista only</li> +</ul> + +<p>The USB driver files are located in the +<code><SDK>/usb_driver</code> directory. For details and +installation instructions, see <a +href="{@docRoot}guide/developing/device.html#setting-up">Setting Up a +Device for Development</a>.</p> +</p> + +<h3>Resolved Issues, Changes</h3> + +<p><strong>Media</strong></p> +<ul> +<li>Updated documentation for {@link android.media.SoundPool +android.media.SoundPool}</li> +<li>{@link android.webkit.WebView} objects no longer automatically save +thumbnails. The {@link android.webkit.WebView#capturePicture() capturePicture()} +method will need to be called manually.</li> +</ul> + +<h3>Known Issues</h3> + +<p><strong>Sensor problems in Emulator</strong></p> + +<ul> +<li>If your application uses the Sensor API and you are running it in the +emulator on the Android 1.5 system image, you may experience problems. Your +application may generate ANR messages or crash when using the sensors. The +problem is being investigated.</li> +</ul> + +<p><strong>Other</strong></p> + +<ul> +<li>We regret to inform developers that Android 1.5 will not include support for +the Zilog Z80 processor architecture.</li> +</ul> + <h2 id="1.1_r1">Android 1.1 SDK, Release 1</h2> -<p>This SDK provides the development tools and Android system image you need to create applications for Android-powered devices. Applications developed on this SDK will be compatible with mobile devices running the Android 1.1 platform. </p> +<p>This SDK provides the development tools and Android system image you need to +create applications for Android-powered devices. Applications developed on this +SDK will be compatible with mobile devices running the Android 1.1 platform. +</p> -<p>This release provides an updated system image (Android 1.1), updated documentation, and the same set of development tools provided in the Android 1.0 r2 SDK. The updated system image includes bug fixes and some smaller features, as well as a few minor API changes from the 1.0 version. </p> +<p>This release provides an updated system image (Android 1.1), updated +documentation, and the same set of development tools provided in the Android 1.0 +r2 SDK. The updated system image includes bug fixes and some smaller features, +as well as a few minor API changes from the 1.0 version. </p> -<p>For details about the Android 1.1 system image included in the SDK — including bug fixes, features, and API changes — please read the <a href="{@docRoot}sdk/android-1.1.html">Android 1.1 Version Notes</a>.</p> +<p>For details about the Android 1.1 system image included in the SDK — +including bug fixes, features, and API changes — please read the <a +href="{@docRoot}sdk/android-1.1.html">Android 1.1 Version Notes</a>.</p> <h3>App Versioning for Android 1.1</h3> -<p>If you are using this SDK to build an application that is compatible <em>only</em> with Android-powered devices running the Android 1.1 platform, please note that you <strong>must</strong> set the the <code>android:minSdkVersion</code> attribute in the application's manifest to the API Level of Android 1.1 — "2".</p> +<p>If you are using this SDK to build an application that is compatible +<em>only</em> with Android-powered devices running the Android 1.1 platform, +please note that you <strong>must</strong> set the the +<code>android:minSdkVersion</code> attribute in the application's manifest to +the API Level of Android 1.1 — "2".</p> -<p>Specifically, you specify the <code>android:minSdkVersion</code> attribute in a <code><uses-sdk></code> element as a child of <code><manifest></code> in the manifest file. When set, the attribute looks like this: </p> +<p>Specifically, you specify the <code>android:minSdkVersion</code> attribute in +a <code><uses-sdk></code> element as a child of +<code><manifest></code> in the manifest file. When set, the attribute +looks like this: </p> <pre><code><manifest> ... @@ -24,13 +212,29 @@ page.title=SDK Release Notes </manifest></code> </pre> -<p>By setting <code>android:minSdkVersion</code> in this way, you ensure that users will only be able to install your application if their devices are running the Android 1.1 platform. In turn, this ensures that your application will function properly on their devices, especially if it uses APIs introduced in Android 1.1. </p> +<p>By setting <code>android:minSdkVersion</code> in this way, you ensure that +users will only be able to install your application if their devices are running +the Android 1.1 platform. In turn, this ensures that your application will +function properly on their devices, especially if it uses APIs introduced in +Android 1.1. </p> -<p>If your application uses APIs introduced in Android 1.1 but does not declare <code><uses-sdk minSdkVersion="2" /></code>, then it will run properly on Android 1.1 devices but <em>not</em> on Android 1.0 devices. </p> +<p>If your application uses APIs introduced in Android 1.1 but does not declare +<code><uses-sdk minSdkVersion="2" /></code>, then it will run properly on +Android 1.1 devices but <em>not</em> on Android 1.0 devices. </p> -<p>If your application does not use any new APIs introduced in Android 1.1, you can indicate Android 1.0 compatibility by removing <code>minSdkVersion</code> or setting the attribute to "1". However, before publishing your application, you must make sure to compile your application against the Android 1.0 system image (available in the Android 1.0 SDK), to ensure that it builds and functions properly for Android 1.0 devices. You should test the application against system images corresponding to the API Levels that the application is designed to be compatible with.</p> +<p>If your application does not use any new APIs introduced in Android 1.1, you +can indicate Android 1.0 compatibility by removing <code>minSdkVersion</code> or +setting the attribute to "1". However, before publishing your application, you +must make sure to compile your application against the Android 1.0 system image +(available in the Android 1.0 SDK), to ensure that it builds and functions +properly for Android 1.0 devices. You should test the application against system +images corresponding to the API Levels that the application is designed to be +compatible with.</p> -<p>If you are sure your application is not using Android 1.1 APIs and has no need to use them, you might find it easier to keep working in the Android 1.0 SDK, rather than migrating to the Android 1.1 SDK and having to do additional testing.</p> +<p>If you are sure your application is not using Android 1.1 APIs and has no +need to use them, you might find it easier to keep working in the Android 1.0 +SDK, rather than migrating to the Android 1.1 SDK and having to do additional +testing.</p> <h3>ADT Plugin Compatibility</h3> @@ -52,7 +256,7 @@ application on the Android 1.1 emulator for the first time.</p> <p>If you're installing the Android SDK for the first time, please see the instructions in <a -href="{@docRoot}sdk/1.1_r1/installing.html">Installing the SDK</a>. +href="{@docRoot}sdk/1.5_r1/installing.html">Installing the SDK</a>. <h3>Other Notes</h3> @@ -136,9 +340,6 @@ are not working in this release.</li> </ul> - - - <h2 id="1.0_r2">Android 1.0 SDK, Release 2</h2> <p>This SDK release includes the Android 1.0 platform and application API. diff --git a/docs/html/sdk/adt_download.jd b/docs/html/sdk/adt_download.jd index 6e9eec4..6d46297 100644 --- a/docs/html/sdk/adt_download.jd +++ b/docs/html/sdk/adt_download.jd @@ -26,11 +26,18 @@ page</a>. </tr> <tr> - <td style="background-color:#ffcccc;">0.8.0</td> - <td style="background-color:#ffcccc;"><a href="http://dl-ssl.google.com/android/ADT-0.8.0.zip">ADT-0.8.0.zip</a></td> - <td style="background-color:#ffcccc;">23 September 2008</td> - <td style="background-color:#ffcccc;">Android 1.1 SDK, Release 1<br />Android 1.0 SDK, Release 1<br /></td> - <td style="background-color:#ffcccc;">Required for users of Android 1.1 SDK, Release 1 and Android 1.0 SDK, Release 1<br /> </td> + <td style="background-color:#ffcccc;">0.9.0</td> + <td style="background-color:#ffcccc;"><a href="http://dl-ssl.google.com/android/ADT-0.9.0.zip">ADT-0.9.0.zip</a></td> + <td style="background-color:#ffcccc;"><nobr>27 April 2009</nobr></td> + <td style="background-color:#ffcccc;"><nobr>Android 1.5 SDK</td> + <td style="background-color:#ffcccc;"><nobr>Required for users of Android 1.5 SDK (and later releases)<br /> </td> + </tr> + <tr> + <td>0.8.0</td> + <td><a href="http://dl-ssl.google.com/android/ADT-0.8.0.zip">ADT-0.8.0.zip</a></td> + <td style="background-color:#ffcccc;"><nobr>23 September 2008</nobr></td> + <td style="background-color:#ffcccc;"><nobr>Android 1.1 SDK<br/>Android 1.0 SDK<br/></td> + <td style="background-color:#ffcccc;"><nobr>Required for users of Android 1.1 SDK and Android 1.0 SDK<br /> </td> </tr> <tr> <td>0.7.1</td> diff --git a/docs/html/sdk/android-1.5-highlights.jd b/docs/html/sdk/android-1.5-highlights.jd new file mode 100644 index 0000000..46022d1 --- /dev/null +++ b/docs/html/sdk/android-1.5-highlights.jd @@ -0,0 +1,205 @@ +page.title=Android 1.5 Platform Highlights +sdk.version=1.5_r1 +@jd:body + +<p> +<em>April 2009</em> +</p> + + +<p>The Android 1.5 platform introduces many new features for users and developers. +The list below provides an overview of the changes. </p> + +<ul> +<li><a href="#ui">UI Localizations</a> +<li><a href="#perf">Resolved Issues</a> +<li><a href="#features">Android 1.5 Platform Highlights</a> +<li><a href="#apis">New APIs and manifest elements</a> +</ul> + +<h2 id="ui">User interface refinements</h4> +<ul> + <li>System-wide: + <ul> + <li>Refinement of all core UI elements</li> + <li>Animated window transitions (off by default)</li> + <li>Accelerometer-based application rotations</li> + </ul> + </li> + <li>UI polish for: + <ul> + <li>In-call experience</li> + <li>Contacts, Call log, and Favorites</li> + <li>SMS & MMS</li> + <li>Browser</li> + <li>Gmail</li> + <li>Calendar</li> + <li>Email</li> + <li>Camera & Gallery</li> + <li>Application management</li> + </ul> + </li> +</ul> + +<h2 id="perf">Performance improvements</h2> + +<ul> +<li>Faster Camera start-up and image capture</li> +<li>Much faster acquisition of GPS location (powered by SUPL AGPS)</li> +<li>Smoother page scrolling in Browser</li> +<li>Speedier GMail conversation list scrolling</li> +</ul> + +<h4 id="features">New features</h4> + +<ul> + <li>On-screen soft keyboard + <ul> + <li>Works in both portrait and landscape orientation</li> + <li>Support for user installation of 3rd party keyboards</li> + <li>User dictionary for custom words</li> + </ul> +</li> + +<li>Home screen + <ul> + <li>Widgets + <ul> + <li>Bundled home screen widgets include: analog clock, calendar, + music player, picture frame, and search</li> + </ul></li> + <li>Live folders</li> + </ul> +</li> + +<li>Camera & Gallery + <ul> + <li>Video recording</li> + <li>Video playback (MPEG-4 & 3GP formats)</li> + </ul> +</li> + +<li>Bluetooth + <ul> + <li>Stereo Bluetooth support (A2DP and AVCRP profiles)</li> + <li>Auto-pairing</li> + <li>Improved handsfree experience</li> + </ul> +</li> + +<li>Browser + <ul> + <li>Updated with latest Webkit browser & Squirrelfish Javascript engines</li> + <li>Copy 'n paste in browser</li> + <li>Search within a page</li> + <li>User-selectable text-encoding</li> + <li>UI changes include: + <ul> + <li>Unified Go and Search box</li> + <li>Tabbed bookmarks/history/most-visited screen</li> + </ul> + </li> + </ul> +</li> + +<li>Contacts + <ul> + <li>Shows user picture for Favorites</li> + <li>Specific date/time stamp for events in call log</li> + <li>One-touch access to a contact card from call log event</li> + </ul> +</li> + +<li>System +<ul> + <li>New Linux kernel (version 2.6.27)</li> + <li>SD card filesystem auto-checking and repair</li> + <li>SIM Application Toolkit 1.0 </li> +</ul> +</li> + +<li>Google applications (not available in the Android 1.5 System Image that is +included in the Android SDK) + <ul> + <li>View Google Talk friends' status in Contacts, SMS, MMS, GMail, and + Email applications</li> + <li>Batch actions such as archive, delete, and label on Gmail messages</li> + <li>Upload videos to Youtube</li> + <li>Upload photos on Picasa</li> + </ul> +</li> +</ul> + +<h4 id="apis">New APIs and manifest elements</h4> + +<ul> +<li>UI framework + <ul> + <li>Framework for easier background/UI thread interaction</li> + <li>New {@link android.widget.SlidingDrawer SlidingDrawer} widget</li> + <li>New {@link android.widget.HorizontalScrollView HorizontalScrollview} widget</li> + </ul> +</li> + +<li>AppWidget framework + <ul> + <li>APIs for creating secure home screen {@link android.appwidget app + widgets}. Also see the <a href="http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html">Introducing home screen widgets and the AppWidget + framework.</li> + <li>APIs for populating {@link android.provider.LiveFolders Live Folders} +with custom content.</li> + </ul> +</li> + +<li>Media framework + <ul> + <li>Raw audio recording and playback APIs</li> + <li>Interactive MIDI playback engine</li> + <li>{@link android.media.MediaRecorder Video Recording APIs} for developers (3GP format).</li> + <li>Video and photo sharing Intents</li> + <li>Media search Intent</li> + </ul> +</li> + +<li>Input Method framework + <ul> + <li>{@link android.inputmethodservice.InputMethodService Input Method + Service} framework</li> + <li>Text-prediction engine</li> + <li>Ability to provide downloadable IMEs to users</li> + </ul> +</li> + +<li>Application-defined hardware requirements + <p>Applications can now use a new element in their manifest files, <a +href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><uses- +configuration></a> to indicate to the Android system what hardware features +they require in order to function properly. For example, an application might +use the element to specify that it requires a physical keyboard or a particular +navigation device, such as a trackball. Prior to installing the application, the +Android system checks the attributes defined for the +<code><uses-configuration></code> element and allows the installation to +continue only if the required hardware is present.</p> +</li> + +<li>Speech recognition framework + <ul> + <li>Support for using speech recognition libraries via Intent. See {@link +android.speech.RecognizerIntent Speech Recognition}.</li> + </ul> +</li> + +<li>Misc API additions + <ul> + <li>LocationManager - Applications can get location change updates via + Intent</li> + <li>WebView - Touch start/end/move/cancel DOM event support</li> + <li>Redesigned {@link android.hardware.SensorManager Sensor Manager + APIs}</li> + <li>GLSurfaceView - convenience framework for creating OpenGL + applications</li> + <li>Broadcast Intent for app update install succeeded - for smoother app + upgrade experience</li> + </ul> +</li> +</ul> diff --git a/docs/html/sdk/android-1.5.jd b/docs/html/sdk/android-1.5.jd index fff911e..c9ab42e 100644 --- a/docs/html/sdk/android-1.5.jd +++ b/docs/html/sdk/android-1.5.jd @@ -8,7 +8,250 @@ sys.date=April 2009 <em>API Level:</em> <strong>3</strong></p> -<p>Please see <a href="{@docRoot}sdk/preview/index.html">Download the Android 1.5 Early Look SDK</a> for more information. </p> +<p>This document provides version notes for the Android 1.5 system image included in the SDK. </p> + +<ul> +<li><a href="#overview">Overview</a> +<li><a href="#overview">External Libraries</a> +<li><a href="#comp">Device Compatibility</a> +<li><a href="#apps">Built-in Applications</a> +<li><a href="#locs">UI Localizations</a> +<!-- <li><a href="#resolved-issues">Resolved Issues</a> --> +<li><a href="#features">Android 1.5 Platform Highlights</a> +<li><a href="#api-changes">API Changes</a> +</ul> + +<h2 id="overview">Overview</h2> + +<p>The Android 1.5 system delivered in the SDK (as library and system image) is +the development counterpart to the Android 1.5 production system image, +deployable to Android-powered handsets starting in May 2009. The system is fully +compliant and includes no external libraries. This is the first version of the +Android SDK that does not include the Maps external library.</p> + +<p>The Android 1.5 system delivers an updated version of the framework +API. As with previous versions, the Android 1.5 API +is assigned an integer identifier — <strong>3</strong> — that is +stored in the system itself. This identifier, called the "API Level", allows the +system to correctly determine whether an application is compatible with +the system, prior to installing the application.</p> + +<p>Applications can reference a specific API Level value in their +manifest files, to indicate the minimum version of the Android system +required to run the application. To reference a minimum API Level, applications +can add a <code>minSdkVersion</code> attribute in their manifest files. +The value of the attribute is an integer corresponding to an API Level +identifier. Prior to installing an application, the system then checks the value of +<code>minSdkVersion</code> and allows the install only +if the referenced integer is less than or equal to the API Level integer stored +in the system itself. </p> + +<p>When you migrate your application to the new SDK, you will need to choose +the platform version against which you will compile your application. In +general, you should compile your application against the lowest possible +version of the platform that your application can support. After you determine +the lowest version, you should ensure that your application's manifest file +defines the API Level of the lowest compatible platform version in the +<code>minSdkVersion</code> attribute. + +<p>After compiling your application, you should make sure to test it on the +platform specified in the application's <code>minSdkVersion</code> attribute. To +ensure forward-compatibility, you should also run the application on platforms +using a higher API Level than that used by your application. To run your +application against different platform versions in the emulator, you create an +AVD for each platform version that you want to test. For more information about +AVDs, see <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual +Devices</a>. If you are using a physical device for testing, ensure that you +know the API Level of the Android platform it runs.</p> + +<p>If you build an application using the Android 1.5 library and your +application makes use of any APIs introduced in API Level 3, you <strong><span +style="color:red;">must</span></strong> set the +<code>android:minSdkVersion</code> attribute in the application's manifest to +"3". </p> + +<p>Specifically, you define the <code>android:minSdkVersion</code> +attribute in a <code><uses-sdk></code> element as a child of +<code><manifest></code> in the manifest file. When set, the +attribute looks like this: </p> + +<pre><manifest> + ... + <uses-sdk minSdkVersion="3" /> + ... +</manifest></pre> + +<p>By setting <code>android:minSdkVersion</code> in this way, you ensure that +users will only be able to install your application if their devices are running +a compatible version of the Android platform. In turn, this ensures that your +application will function properly on their devices. This is especially +important if your application uses <a href="#apichange">APIs or system features +introduced in Android 1.5</a>. </p> + +<p>If your application uses APIs introduced in Android 1.5 but does not +declare <code><uses-sdk minSdkVersion="3" /></code>, then it will +run properly on Android 1.5 devices but <em>not</em> on Android 1.0 +devices. In the latter case, the application will crash at runtime when +it tries to use the Android 1.5 APIs.</p> + +<p>Conversely, if your application does not use any new APIs introduced in +Android 1.5, the application will in most cases function normally on devices +running a later version of the platform. However, if you have published +the application, you are strongly encouraged to install and test your +application on the Android 1.5 system image included in the SDK. This will +ensure a smooth transition for users, as they upgrade their devices to +the new version of the Android platform. </p> + +<p>Finally, if your application does not use any new APIs introduced since +Android 1.1, you can indicate general Android 1.1 compatibility by +setting the attribute to "2". If your application does not use any +new APIs introduced since Android 1.0, you can remove the attribute or +set it to "1". However, +before publishing your application, you must make sure to compile your +application against the Android library that corresponds to the application's +<code>minSdkVeresion</code> value.</p> + +<h2 id="apps">Built-in Applications</h2> + +<p>The system image includes these built-in applications:</p> + <ul> + <li>Alarm Clock</li> + <li>Browser</li> + <li>Calculator</li> + <li>Camcorder</li> + <li>Camera</li> + <li>Contacts</li> + <li>Custom Locale (developer app)</li> + <li>Dev Tools (developer app)</li> + <li>Dialer</li> + <li>Email</li> + <li>Gallery</li> + <li>Messaging</li> + <li>Music</li> + <li>Settings</li> + <li>Spare Parts (developer app)</li> + </ul> + +<h2 id="locs">Locales</h2> + +<p>The system image provides a variety of built-in locales. In some cases, +region-specific strings are available for the locales. In other cases, +a default version of the language is used. The languages that will be +available in the Android 1.5 system image are listed below (with +<em>language</em>_<em>country/region</em> locale descriptor).</p> + +<div class="g-unit g-first" style="whitespace:nowrap;width:35%;"> +<ul> +<li>Chinese, PRC (zh_CN)</li> +<li>Chinese, Taiwan (zh_TW)</li> +<li>Czech (cs_CZ)</li> +<li>Dutch, Netherlands (nl_NL)</li> +<li>Dutch, Belgium (nl_BE)</li> +<li>English, US (en_US)</li> +<li>English, Britain (en_GB)</li> +<li>English, Canada(en_CA)</li> +<li>English, Australia (en_AU)</li> +<li>English, New Zealand (en_NZ)</li> +<li>English, Singapore(en_SG)</li> +<li>French, France (fr_FR)</li> +</div> +<div class="g-unit" style="whitespace:nowrap;"> +<li>French, Belgium (fr_BE)</li> +<li>French, Canada (fr_CA)</li> +<li>French, Switzerland (fr_CH)</li> +<li>German, Germany (de_DE)</li> +<li>German, Austria(de_AT)</li> +<li>German, Switzerland (de_CH)</li> +<li>German, Liechtenstein (de_LI)</li> +<li>Italian, Italy (it_IT)</li> +<li>Italian, Switzerland (it_CH)</li> +<li>Japanese (ja_JP)</li> +<li>Korean (ko_KR)</li> +<li>Polish (pl_PL)</li> +<li>Russian (ru_RU)</li> +<li>Spanish (es_ES)</li> +</ul> +</div> + +<p>Localized UI strings match the locales that are displayable in +the emulator, accessible through the device Settings application.</p> + +<!-- +<h2 id="resolved-issues">Resolved Issues</h2> +<ul> +<li><font color="red"><strong></strong></font></li> +</ul> +--> + +<h2 id="features">New Features</h2> + +<p>For a list of new system features, see the <a +href="{@docRoot}sdk/android-1.5-highlights.html">Android 1.5 Platform +Highlights</a> document.</p> + +<h2 id="api-changes">API Changes</h2> + +<h3>Overview</strong></h3> + +<ul> + <li>UI framework</li> + <ul> + <li>Framework for easier background/UI thread interaction</li> + <li>New SlidingDrawer widget</li> + <li>Horizontal ScrollView widget</li> + </ul> + + <li>Home Screen framework</li> + <ul> + <li>APIs for creating secure home screen widgets</li> + <li>APIs for populating live folders with custom content</li> + </ul> + + <li>Media framework</li> + <ul> + <li>Raw audio recording and playback APIs</li> + <li>Interactive MIDI playback engine</li> + <li>Video recording APIs for developers (3GP format)</li> + <li>Video and photo sharing Intents</li> + <li>Media search Intent</li> + </ul> + <li>Input Method framework </li> + <ul> + <li>Text prediction engine</li> + <li>Ability to provide downloadable IMEs to users</li> + </ul> +<li>Application-defined hardware requirements +<p>Applications can now use a new element in their manifest files, <a +href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"> +<uses-configuration></a> to indicate to the Android system what hardware +features they require in order to function properly. For example, an application +might use the element to specify that it requires a physical keyboard or a +particular navigation device, such as a trackball. Prior to installing the +application, the Android system checks the attributes defined for the +<code><uses-configuration></code> element and allows the installation to +continue only if the required hardware is present.</p></li> + <li>Speech recognition framework</li> + <ul> + <li>Support for using speech recognition libraries via Intent</li> + </ul> + <li>Misc API additions</li> + <ul> + <li> LocationManager - Applications can get location change updates via +Intent</li> + <li>WebView - Touch start/end/move/cancel DOM event support</li> + <li>SensorManager - redesigned sensor APIs</li> + <li>GLSurfaceView - convenience framework for creating OpenGL +applications</li> + <li>Broadcast Intent for app update install succeeded - for smoother app +upgrade experience</li> + </ul> + +</ul> + +<h3>API Change Details</h3> + +<p>For a detailed view of API changes in this platform (API Level 3), see the <a +href="{@docRoot}sdk/api_diff/3/changes.html">API Differences Report</a>.</p> diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 8c7a0a7..1e5122f 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -2,17 +2,17 @@ <ul> <li><?cs if:android.whichdoc != "online" ?> - <h2>Android 1.5 SDK, r1</h2><?cs + <h2>Android <?cs var:sdk.version ?> SDK, r<?cs var:sdk.rel.id ?></h2><?cs else ?> <h2>Current SDK Release</h2><?cs /if ?> <ul><?cs if:android.whichdoc == "online" ?> - <li><a href="<?cs var:toroot ?>sdk/1.1_r1/index.html">Download</a></li><?cs + <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/index.html">Download</a></li><?cs /if ?> - <li><a href="<?cs var:toroot ?>sdk/1.1_r1/installing.html">Installing</a></li> - <li><a href="<?cs var:toroot ?>sdk/1.1_r1/upgrading.html">Upgrading</a></li> - <li><a href="<?cs var:toroot ?>sdk/1.1_r1/requirements.html">System Requirements</a></li> + <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/installing.html">Installing</a></li> + <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/upgrading.html">Upgrading</a></li> + <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/requirements.html">System Requirements</a></li> </ul> <ul> <li><a href="<?cs var:toroot ?>sdk/terms.html">SDK Terms and Conditions</a></li> @@ -20,7 +20,7 @@ </ul><?cs if:android.whichdoc == "online" ?> <li> - <h2>Android System Images</h2> + <h2>System Image Version Notes</h2> <ul> <li><a href="<?cs var:toroot ?>sdk/android-1.5.html">Android 1.5 Version Notes</a></li> <li><a href="<?cs var:toroot ?>sdk/android-1.1.html">Android 1.1 Version Notes</a></li> @@ -29,8 +29,9 @@ <li> <h2>Previous SDK Releases</h2> <ul> - <li><a href="<?cs var:toroot ?>sdk/1.0_r2/index.html">Android 1.0 SDK, release 2</a></li> - <li><a href="<?cs var:toroot ?>sdk/1.0_r1/index.html">Android 1.0 SDK, release 1</a></li> + <li><a href="<?cs var:toroot ?>sdk/1.1_r1/index.html">Android 1.1 SDK, r1</a></li> + <li><a href="<?cs var:toroot ?>sdk/1.0_r2/index.html">Android 1.0 SDK, r2</a></li> + <li><a href="<?cs var:toroot ?>sdk/1.0_r1/index.html">Android 1.0 SDK, r1</a></li> <li><a href="<?cs var:toroot ?>sdk/older_releases.html">Older Releases</a></li> </ul> </li><?cs diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java index 2681eae..f549900 100644 --- a/graphics/java/android/graphics/Matrix.java +++ b/graphics/java/android/graphics/Matrix.java @@ -16,6 +16,8 @@ package android.graphics; +import java.io.PrintWriter; + /** * The Matrix class holds a 3x3 matrix for transforming coordinates. @@ -539,17 +541,49 @@ public class Matrix { } public String toString() { - return "Matrix{" + toShortString() + "}"; + StringBuilder sb = new StringBuilder(64); + sb.append("Matrix{"); + toShortString(sb); + sb.append('}'); + return sb.toString(); } public String toShortString() { + StringBuilder sb = new StringBuilder(64); + toShortString(sb); + return sb.toString(); + } + + /** + * @hide + */ + public void toShortString(StringBuilder sb) { + float[] values = new float[9]; + getValues(values); + sb.append('['); + sb.append(values[0]); sb.append(", "); sb.append(values[1]); sb.append(", "); + sb.append(values[2]); sb.append("]["); + sb.append(values[3]); sb.append(", "); sb.append(values[4]); sb.append(", "); + sb.append(values[5]); sb.append("]["); + sb.append(values[6]); sb.append(", "); sb.append(values[7]); sb.append(", "); + sb.append(values[8]); sb.append(']'); + } + + /** + * Print short string, to optimize dumping. + * @hide + */ + public void printShortString(PrintWriter pw) { float[] values = new float[9]; getValues(values); - return "[" + - values[0] + ", " + values[1] + ", " + values[2] + "][" + - values[3] + ", " + values[4] + ", " + values[5] + "][" + - values[6] + ", " + values[7] + ", " + values[8] + "]"; + pw.print('['); + pw.print(values[0]); pw.print(", "); pw.print(values[1]); pw.print(", "); + pw.print(values[2]); pw.print("]["); + pw.print(values[3]); pw.print(", "); pw.print(values[4]); pw.print(", "); + pw.print(values[5]); pw.print("]["); + pw.print(values[6]); pw.print(", "); pw.print(values[7]); pw.print(", "); + pw.print(values[8]); pw.print(']'); } diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 2005344..7022acf 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -19,6 +19,8 @@ package android.graphics; import android.os.Parcel; import android.os.Parcelable; +import java.io.PrintWriter; + /** * Rect holds four integer coordinates for a rectangle. The rectangle is * represented by the coordinates of its 4 edges (left, top, right bottom). @@ -78,14 +80,40 @@ public final class Rect implements Parcelable { } public String toString() { - return "Rect(" + left + ", " + top + " - " + right + ", " + bottom + ")"; + StringBuilder sb = new StringBuilder(32); + sb.append("Rect("); sb.append(left); sb.append(", "); + sb.append(top); sb.append(" - "); sb.append(right); + sb.append(", "); sb.append(bottom); sb.append(")"); + return sb.toString(); } /** * Return a string representation of the rectangle in a compact form. */ public String toShortString() { - return "[" + left + "," + top + "][" + right + "," + bottom + "]"; + return toShortString(new StringBuilder(32)); + } + + /** + * Return a string representation of the rectangle in a compact form. + * @hide + */ + public String toShortString(StringBuilder sb) { + sb.setLength(0); + sb.append('['); sb.append(left); sb.append(','); + sb.append(top); sb.append("]["); sb.append(right); + sb.append(','); sb.append(bottom); sb.append(']'); + return sb.toString(); + } + + /** + * Print short representation to given writer. + * @hide + */ + public void printShortString(PrintWriter pw) { + pw.print('['); pw.print(left); pw.print(','); + pw.print(top); pw.print("]["); pw.print(right); + pw.print(','); pw.print(bottom); pw.print(']'); } /** diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index 7164b78..6aa40d00 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -312,7 +312,6 @@ private: bool processAudioBuffer(const sp<ClientRecordThread>& thread); - sp<IAudioFlinger> mAudioFlinger; sp<IAudioRecord> mAudioRecord; sp<IMemory> mCblkMemory; sp<ClientRecordThread> mClientRecordThread; diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 7645978..ba0467c 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -383,7 +383,6 @@ private: bool processAudioBuffer(const sp<AudioTrackThread>& thread); - sp<IAudioFlinger> mAudioFlinger; sp<IAudioTrack> mAudioTrack; sp<IMemory> mCblkMemory; sp<AudioTrackThread> mAudioTrackThread; diff --git a/include/ui/Camera.h b/include/ui/Camera.h index e593fea..12fa20f 100644 --- a/include/ui/Camera.h +++ b/include/ui/Camera.h @@ -78,8 +78,8 @@ class Camera : public BnCameraClient, public IBinder::DeathRecipient { public: // construct a camera client from an existing remote - Camera(const sp<ICamera>& camera); - + Camera(const sp<ICamera>& camera); // to be removed + static sp<Camera> create(const sp<ICamera>& camera); static sp<Camera> connect(); ~Camera(); void init(); diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index d01d83f..9b8c302 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -988,119 +988,225 @@ struct ResTable_config return diffs; } - // Return true if 'this' is more specific than 'o'. Optionally, if - // 'requested' is null, then they will also be compared against the - // requested configuration and true will only be returned if 'this' - // is a better candidate than 'o' for the configuration. This assumes that - // match() has already been used to remove any configurations that don't - // match the requested configuration at all; if they are not first filtered, - // non-matching results can be considered better than matching ones. + // Return true if 'this' is more specific than 'o'. inline bool - isBetterThan(const ResTable_config& o, const ResTable_config* requested = NULL) const { + isMoreSpecificThan(const ResTable_config& o) const { // The order of the following tests defines the importance of one // configuration parameter over another. Those tests first are more // important, trumping any values in those following them. - if (imsi != 0 && (!requested || requested->imsi != 0)) { - if (mcc != 0 && (!requested || requested->mcc != 0)) { - if (o.mcc == 0) { - return true; - } + if (imsi || o.imsi) { + if (mcc != o.mcc) { + if (!mcc) return false; + if (!o.mcc) return true; } - if (mnc != 0 && (!requested || requested->mnc != 0)) { - if (o.mnc == 0) { - return true; - } + + if (mnc != o.mnc) { + if (!mnc) return false; + if (!o.mnc) return true; } } - if (locale != 0 && (!requested || requested->locale != 0)) { - if (language[0] != 0 && (!requested || requested->language[0] != 0)) { - if (o.language[0] == 0) { - return true; - } + + if (locale || o.locale) { + if (language[0] != o.language[0]) { + if (!language[0]) return false; + if (!o.language[0]) return true; } - if (country[0] != 0 && (!requested || requested->country[0] != 0)) { - if (o.country[0] == 0) { - return true; - } + + if (country[0] != o.country[0]) { + if (!country[0]) return false; + if (!o.country[0]) return true; } } - if (screenType != 0 && (!requested || requested->screenType != 0)) { - if (orientation != 0 && (!requested || requested->orientation != 0)) { - if (o.orientation == 0) { - return true; - } + + if (screenType || o.screenType) { + if (orientation != o.orientation) { + if (!orientation) return false; + if (!o.orientation) return true; } - if (density != 0 && (!requested || requested->density != 0)) { - if (o.density == 0) { - return true; - } + + // density is never 'more specific' + // as the default just equals 160 + + if (touchscreen != o.touchscreen) { + if (!touchscreen) return false; + if (!o.touchscreen) return true; } - if (touchscreen != 0 && (!requested || requested->touchscreen != 0)) { - if (o.touchscreen == 0) { - return true; - } + } + + if (input || o.input) { + if (inputFlags != o.inputFlags) { + if (!(inputFlags & MASK_KEYSHIDDEN)) return false; + if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true; + } + + if (keyboard != o.keyboard) { + if (!keyboard) return false; + if (!o.keyboard) return true; + } + + if (navigation != o.navigation) { + if (!navigation) return false; + if (!o.navigation) return true; } } - if (input != 0 && (!requested || requested->input != 0)) { - const int keysHidden = inputFlags&MASK_KEYSHIDDEN; - const int reqKeysHidden = requested - ? requested->inputFlags&MASK_KEYSHIDDEN : 0; - if (keysHidden != 0 && reqKeysHidden != 0) { - const int oKeysHidden = o.inputFlags&MASK_KEYSHIDDEN; - //LOGI("isBetterThan keysHidden: cur=%d, given=%d, config=%d\n", - // keysHidden, oKeysHidden, reqKeysHidden); - if (oKeysHidden == 0) { - //LOGI("Better because 0!"); - return true; + + if (screenSize || o.screenSize) { + if (screenWidth != o.screenWidth) { + if (!screenWidth) return false; + if (!o.screenWidth) return true; + } + + if (screenHeight != o.screenHeight) { + if (!screenHeight) return false; + if (!o.screenHeight) return true; + } + } + + if (version || o.version) { + if (sdkVersion != o.sdkVersion) { + if (!sdkVersion) return false; + if (!o.sdkVersion) return true; + } + + if (minorVersion != o.minorVersion) { + if (!minorVersion) return false; + if (!o.minorVersion) return true; + } + } + return false; + } + + // Return true if 'this' is a better match than 'o' for the 'requested' + // configuration. This assumes that match() has already been used to + // remove any configurations that don't match the requested configuration + // at all; if they are not first filtered, non-matching results can be + // considered better than matching ones. + // The general rule per attribute: if the request cares about an attribute + // (it normally does), if the two (this and o) are equal it's a tie. If + // they are not equal then one must be generic because only generic and + // '==requested' will pass the match() call. So if this is not generic, + // it wins. If this IS generic, o wins (return false). + inline bool + isBetterThan(const ResTable_config& o, + const ResTable_config* requested) const { + if (requested) { + if (imsi || o.imsi) { + if ((mcc != o.mcc) && requested->mcc) { + return (mcc); } - // For compatibility, we count KEYSHIDDEN_NO as being - // the same as KEYSHIDDEN_SOFT. Here we disambiguate these - // may making an exact match more specific. - if (keysHidden == reqKeysHidden && oKeysHidden != reqKeysHidden) { - // The current configuration is an exact match, and - // the given one is not, so the current one is better. - //LOGI("Better because other not same!"); - return true; + + if ((mnc != o.mnc) && requested->mnc) { + return (mnc); } } - if (keyboard != 0 && (!requested || requested->keyboard != 0)) { - if (o.keyboard == 0) { - return true; + + if (locale || o.locale) { + if ((language[0] != o.language[0]) && requested->language[0]) { + return (language[0]); } - } - if (navigation != 0 && (!requested || requested->navigation != 0)) { - if (o.navigation == 0) { - return true; + + if ((country[0] != o.country[0]) && requested->country[0]) { + return (country[0]); } } - } - if (screenSize != 0 && (!requested || requested->screenSize != 0)) { - if (screenWidth != 0 && (!requested || requested->screenWidth != 0)) { - if (o.screenWidth == 0) { - return true; + + if (screenType || o.screenType) { + if ((orientation != o.orientation) && requested->orientation) { + return (orientation); + } + + if (density != o.density) { + // density is tough. Any density is potentially useful + // because the system will scale it. Scaling down + // is generally better than scaling up. + // Default density counts as 160dpi (the system default) + // TODO - remove 160 constants + int h = (density?density:160); + int l = (o.density?o.density:160); + bool bImBigger = true; + if (l > h) { + int t = h; + h = l; + l = t; + bImBigger = false; + } + + int reqValue = (requested->density?requested->density:160); + if (reqValue >= h) { + // requested value higher than both l and h, give h + return bImBigger; + } + if (l >= reqValue) { + // requested value lower than both l and h, give l + return !bImBigger; + } + // saying that scaling down is 2x better than up + if (((2 * l) - reqValue) * h > reqValue * reqValue) { + return !bImBigger; + } else { + return bImBigger; + } + } + + if ((touchscreen != o.touchscreen) && requested->touchscreen) { + return (touchscreen); } } - if (screenHeight != 0 && (!requested || requested->screenHeight != 0)) { - if (o.screenHeight == 0) { - return true; + + if (input || o.input) { + const int keysHidden = inputFlags & MASK_KEYSHIDDEN; + const int oKeysHidden = o.inputFlags & MASK_KEYSHIDDEN; + if (keysHidden != oKeysHidden) { + const int reqKeysHidden = + requested->inputFlags & MASK_KEYSHIDDEN; + if (reqKeysHidden) { + + if (!keysHidden) return false; + if (!oKeysHidden) return true; + // For compatibility, we count KEYSHIDDEN_NO as being + // the same as KEYSHIDDEN_SOFT. Here we disambiguate + // these by making an exact match more specific. + if (reqKeysHidden == keysHidden) return true; + if (reqKeysHidden == oKeysHidden) return false; + } + } + + if ((keyboard != o.keyboard) && requested->keyboard) { + return (keyboard); + } + + if ((navigation != o.navigation) && requested->navigation) { + return (navigation); } } - } - if (version != 0 && (!requested || requested->version != 0)) { - if (sdkVersion != 0 && (!requested || requested->sdkVersion != 0)) { - if (o.sdkVersion == 0) { - return true; + + if (screenSize || o.screenSize) { + if ((screenWidth != o.screenWidth) && requested->screenWidth) { + return (screenWidth); + } + + if ((screenHeight != o.screenHeight) && + requested->screenHeight) { + return (screenHeight); } } - if (minorVersion != 0 && (!requested || requested->minorVersion != 0)) { - if (o.minorVersion == 0) { - return true; + + if (version || o.version) { + if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) { + return (sdkVersion); + } + + if ((minorVersion != o.minorVersion) && + requested->minorVersion) { + return (minorVersion); } } + + return false; } - return false; + return isMoreSpecificThan(o); } - + // Return true if 'this' can be considered a match for the parameters in // 'settings'. // Note this is asymetric. A default piece of data will match every request @@ -1137,8 +1243,7 @@ struct ResTable_config && orientation != settings.orientation) { return false; } - // Density not taken into account, always match, no matter what - // density is specified for the resource + // density always matches - we can scale it. See isBetterThan if (settings.touchscreen != 0 && touchscreen != 0 && touchscreen != settings.touchscreen) { return false; diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index d11e13a..b56221f 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -651,27 +651,30 @@ status_t AudioFlinger::setStreamVolume(int stream, float value) return BAD_VALUE; } - mHardwareMixerThread->setStreamVolume(stream, value); -#ifdef WITH_A2DP - mA2dpMixerThread->setStreamVolume(stream, value); -#endif - status_t ret = NO_ERROR; if (stream == AudioSystem::VOICE_CALL || stream == AudioSystem::BLUETOOTH_SCO) { - + float hwValue; if (stream == AudioSystem::VOICE_CALL) { - value = (float)AudioSystem::logToLinear(value)/100.0f; + hwValue = (float)AudioSystem::logToLinear(value)/100.0f; + // offset value to reflect actual hardware volume that never reaches 0 + // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java) + value = 0.01 + 0.99 * value; } else { // (type == AudioSystem::BLUETOOTH_SCO) - value = 1.0f; + hwValue = 1.0f; } AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_SET_VOICE_VOLUME; - ret = mAudioHardware->setVoiceVolume(value); + ret = mAudioHardware->setVoiceVolume(hwValue); mHardwareStatus = AUDIO_HW_IDLE; } + mHardwareMixerThread->setStreamVolume(stream, value); +#ifdef WITH_A2DP + mA2dpMixerThread->setStreamVolume(stream, value); +#endif + return ret; } @@ -709,7 +712,14 @@ float AudioFlinger::streamVolume(int stream) const if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { return 0.0f; } - return mHardwareMixerThread->streamVolume(stream); + + float volume = mHardwareMixerThread->streamVolume(stream); + // remove correction applied by setStreamVolume() + if (stream == AudioSystem::VOICE_CALL) { + volume = (volume - 0.01) / 0.99 ; + } + + return volume; } bool AudioFlinger::streamMute(int stream) const @@ -812,17 +822,12 @@ void AudioFlinger::handleForcedSpeakerRoute(int command) if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) { LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER); mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - mAudioHardware->setMasterVolume(0); usleep(mHardwareMixerThread->latency()*1000); mHardwareStatus = AUDIO_HW_SET_ROUTING; mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER); mHardwareStatus = AUDIO_HW_IDLE; // delay track start so that audio hardware has time to siwtch routes usleep(kStartSleepTime); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume()); - mHardwareStatus = AUDIO_HW_IDLE; } mForcedRoute = AudioSystem::ROUTE_SPEAKER; } @@ -1480,18 +1485,6 @@ status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track) return status; } -// removeTrack_l() must be called with AudioFlinger::mLock held -void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name) -{ - sp<Track> t = track.promote(); - if (t!=NULL && (t->mState <= TrackBase::STOPPED)) { - t->reset(); - deleteTrackName_l(name); - removeActiveTrack_l(track); - mAudioFlinger->mWaitWorkCV.broadcast(); - } -} - // destroyTrack_l() must be called with AudioFlinger::mLock held void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track) { @@ -1697,7 +1690,7 @@ void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t // Check validity of returned pointer in case the track control block would have been corrupted. if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd || - cblk->channels == 2 && ((unsigned long)bufferStart & 3) ) { + (cblk->channels == 2 && ((unsigned long)bufferStart & 3))) { LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ server %d, serverBase %d, user %d, userBase %d, channels %d", bufferStart, bufferEnd, mBuffer, mBufferEnd, @@ -1733,7 +1726,6 @@ AudioFlinger::MixerThread::Track::~Track() wp<Track> weak(this); // never create a strong ref from the dtor Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); mState = TERMINATED; - mMixerThread->removeTrack_l(weak, mName); } void AudioFlinger::MixerThread::Track::destroy() diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index db5cc74..c7ca9ec 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -501,7 +501,6 @@ private: MixerThread& operator = (const MixerThread&); status_t addTrack_l(const sp<Track>& track); - void removeTrack_l(wp<Track> track, int name); void destroyTrack_l(const sp<Track>& track); int getTrackName_l(); void deleteTrackName_l(int name); diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp index ac76a19..cc1bd8f 100644 --- a/libs/audioflinger/AudioHardwareInterface.cpp +++ b/libs/audioflinger/AudioHardwareInterface.cpp @@ -53,7 +53,7 @@ static const char* routeStrings[] = "EARPIECE ", "SPEAKER ", "BLUETOOTH ", - "HEADSET " + "HEADSET ", "BLUETOOTH_A2DP " }; static const char* routeNone = "NONE"; diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp index b3cbda1..0fba82c 100644 --- a/libs/ui/Camera.cpp +++ b/libs/ui/Camera.cpp @@ -75,6 +75,19 @@ Camera::Camera(const sp<ICamera>& camera) } } + +sp<Camera> Camera::create(const sp<ICamera>& camera) +{ + sp<Camera> c = new Camera(); + // connect this client to existing camera remote + if (camera->connect(c) == NO_ERROR) { + c->mStatus = NO_ERROR; + c->mCamera = camera; + camera->asBinder()->linkToDeath(c); + } + return c; +} + void Camera::init() { mStatus = UNKNOWN_ERROR; diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 2ad3bfe..3d12dca 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -1820,7 +1820,7 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag } } - if (bestPackage != NULL && bestItem.isBetterThan(thisConfig)) { + if (bestPackage != NULL && bestItem.isMoreSpecificThan(thisConfig)) { continue; } diff --git a/location/java/android/location/Geocoder.java b/location/java/android/location/Geocoder.java index 2ce1273..53e46b7 100644 --- a/location/java/android/location/Geocoder.java +++ b/location/java/android/location/Geocoder.java @@ -36,11 +36,11 @@ import java.util.List; * coordinate into a (partial) address. The amount of detail in a * reverse geocoded location description may vary, for example one * might contain the full street address of the closest building, while - * another might contain only a city name and postal code. + * another might contain only a city name and postal code. * * The Geocoder class requires a backend service that is not included in - * the core android framework. The Geocoder query methods will return an - * empty list if there no backend service in the platform. + * the core android framework. The Geocoder query methods will return an + * empty list if there no backend service in the platform. */ public final class Geocoder { private static final String TAG = "Geocoder"; diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 7d35814..096622a 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -45,7 +45,10 @@ interface ILocationManager boolean addGpsStatusListener(IGpsStatusListener listener); void removeGpsStatusListener(IGpsStatusListener listener); - + + // for reporting callback completion + void locationCallbackFinished(ILocationListener listener); + boolean sendExtraCommand(String provider, String command, inout Bundle extras); void addProximityAlert(double latitude, double longitude, float distance, diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 0c7254e..f587f96 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -194,6 +194,11 @@ public class LocationManager { mListener.onProviderDisabled((String) msg.obj); break; } + try { + mService.locationCallbackFinished(this); + } catch (RemoteException e) { + Log.e(TAG, "locationCallbackFinished: RemoteException", e); + } } } /** diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index d0fa795..5917ab9 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -200,7 +200,7 @@ public class AudioSystem * param error error code: * - AUDIO_STATUS_OK * - AUDIO_STATUS_SERVER_DIED - * - UDIO_STATUS_ERROR + * - AUDIO_STATUS_ERROR */ void onError(int error); }; diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index fc8476d..ae3e181 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -453,11 +453,12 @@ public class MediaScanner FileCacheEntry entry = beginFile(path, mimeType, lastModified, fileSize); // rescan for metadata if file was modified since last scan if (entry != null && (entry.mLastModifiedChanged || scanAlways)) { - boolean ringtones = (path.indexOf(RINGTONES_DIR) > 0); - boolean notifications = (path.indexOf(NOTIFICATIONS_DIR) > 0); - boolean alarms = (path.indexOf(ALARMS_DIR) > 0); - boolean podcasts = (path.indexOf(PODCAST_DIR) > 0); - boolean music = (path.indexOf(MUSIC_DIR) > 0) || + String lowpath = path.toLowerCase(); + boolean ringtones = (lowpath.indexOf(RINGTONES_DIR) > 0); + boolean notifications = (lowpath.indexOf(NOTIFICATIONS_DIR) > 0); + boolean alarms = (lowpath.indexOf(ALARMS_DIR) > 0); + boolean podcasts = (lowpath.indexOf(PODCAST_DIR) > 0); + boolean music = (lowpath.indexOf(MUSIC_DIR) > 0) || (!ringtones && !notifications && !alarms && !podcasts); if (mFileType == MediaFile.FILE_TYPE_MP3 || diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 986f88e..1720af0 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -73,7 +73,6 @@ AudioRecord::~AudioRecord() // Otherwise the callback thread will never exit. stop(); if (mClientRecordThread != 0) { - mCblk->cv.signal(); mClientRecordThread->requestExitAndWait(); mClientRecordThread.clear(); } @@ -96,7 +95,7 @@ status_t AudioRecord::set( { LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount); - if (mAudioFlinger != 0) { + if (mAudioRecord != 0) { return INVALID_OPERATION; } @@ -181,7 +180,6 @@ status_t AudioRecord::set( mStatus = NO_ERROR; - mAudioFlinger = audioFlinger; mAudioRecord = record; mCblkMemory = cblk; mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); @@ -293,6 +291,7 @@ status_t AudioRecord::stop() } if (android_atomic_and(~1, &mActive) == 1) { + mCblk->cv.signal(); mAudioRecord->stop(); // the record head position will reset to 0, so if a marker is set, we need // to activate it again @@ -375,6 +374,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) status_t result; audio_track_cblk_t* cblk = mCblk; uint32_t framesReq = audioBuffer->frameCount; + uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS; audioBuffer->frameCount = 0; audioBuffer->size = 0; @@ -391,9 +391,9 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) if (UNLIKELY(!waitCount)) return WOULD_BLOCK; timeout = 0; - result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS)); + result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); if (__builtin_expect(result!=NO_ERROR, false)) { - cblk->waitTimeMs += WAIT_PERIOD_MS; + cblk->waitTimeMs += waitTimeMs; if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { LOGW( "obtainBuffer timed out (is the CPU pegged?) " "user=%08x, server=%08x", cblk->user, cblk->server); @@ -520,7 +520,7 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) status_t err = obtainBuffer(&audioBuffer, 1); if (err < NO_ERROR) { if (err != TIMED_OUT) { - LOGE("Error obtaining an audio buffer, giving up."); + LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up."); return false; } break; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 24f7281..289bd75 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -92,7 +92,6 @@ AudioTrack::~AudioTrack() // Otherwise the callback thread will never exit. stop(); if (mAudioTrackThread != 0) { - mCblk->cv.signal(); mAudioTrackThread->requestExitAndWait(); mAudioTrackThread.clear(); } @@ -117,7 +116,7 @@ status_t AudioTrack::set( LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); - if (mAudioFlinger != 0) { + if (mAudioTrack != 0) { LOGE("Track already in use"); return INVALID_OPERATION; } @@ -228,7 +227,6 @@ status_t AudioTrack::set( mStatus = NO_ERROR; - mAudioFlinger = audioFlinger; mAudioTrack = track; mCblkMemory = cblk; mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); @@ -357,6 +355,7 @@ void AudioTrack::stop() } if (android_atomic_and(~1, &mActive) == 1) { + mCblk->cv.signal(); mAudioTrack->stop(); // Cancel loops (If we are in the middle of a loop, playback // would not stop until loopCount reaches 0). @@ -596,6 +595,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) status_t result; audio_track_cblk_t* cblk = mCblk; uint32_t framesReq = audioBuffer->frameCount; + uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS; audioBuffer->frameCount = 0; audioBuffer->size = 0; @@ -614,9 +614,9 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) if (UNLIKELY(!waitCount)) return WOULD_BLOCK; timeout = 0; - result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS)); + result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); if (__builtin_expect(result!=NO_ERROR, false)) { - cblk->waitTimeMs += WAIT_PERIOD_MS; + cblk->waitTimeMs += waitTimeMs; if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { // timing out when a loop has been set and we have already written upto loop end // is a normal condition: no need to wake AudioFlinger up. @@ -798,7 +798,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) status_t err = obtainBuffer(&audioBuffer, 1); if (err < NO_ERROR) { if (err != TIMED_OUT) { - LOGE("Error obtaining an audio buffer, giving up."); + LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up."); return false; } break; diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 5cbb25c..52bd7d4 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -336,7 +336,7 @@ public: { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - remote()->transact(WAKE_UP, data, &reply); + remote()->transact(WAKE_UP, data, &reply, IBinder::FLAG_ONEWAY); return; } diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp index 5feb11f..9d00aef 100644 --- a/media/libmedia/IAudioFlingerClient.cpp +++ b/media/libmedia/IAudioFlingerClient.cpp @@ -43,7 +43,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor()); data.writeInt32((int)enabled); - remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply); + remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); } }; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java index 07b43bb..281828f 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java @@ -464,6 +464,7 @@ public class MediaNames { public static final String RECORDED_SQVGA_H263 = "/sdcard/SQVGA_H263.3gp"; public static final String RECORDED_CIF_H263 = "/sdcard/CIF_H263.3gp"; public static final String RECORDED_QCIF_H263 = "/sdcard/QCIF_H263.3gp"; + public static final String RECORDED_PORTRAIT_H263 = "/sdcard/QCIF_mp4.3gp"; public static final String RECORDED_HVGA_MP4 = "/sdcard/HVGA_mp4.mp4"; public static final String RECORDED_QVGA_MP4 = "/sdcard/QVGA_mp4.mp4"; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java index 65451c5..261b4f4 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java @@ -22,6 +22,7 @@ import com.android.mediaframeworktest.MediaNames; import java.io.*; import android.content.Context; +import android.hardware.Camera; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.test.ActivityInstrumentationTestCase; @@ -46,6 +47,7 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram private SurfaceHolder mSurfaceHolder = null; private MediaRecorder mRecorder; Context mContext; + Camera mCamera; public MediaRecorderTest() { super("com.android.mediaframeworktest", MediaFrameworkTest.class); @@ -234,12 +236,32 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram assertTrue("QCIFH263 Video Only", videoRecordedResult); } - @Suppress - public void testPortraitH263() throws Exception { + @LargeTest + /* + * This test case set the camera in portrait mode. + * Verification: validate the video dimension and the duration. + */ + public void testPortraitH263() throws Exception { boolean videoRecordedResult = false; - recordVideo(15, 144, 176, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true); - videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 144, 176); + try { + mCamera = Camera.open(); + Camera.Parameters parameters = mCamera.getParameters(); + parameters.setPreviewSize(352, 288); + parameters.set("orientation", "portrait"); + mCamera.setParameters(parameters); + mCamera.unlock(); + mRecorder.setCamera(mCamera); + Thread.sleep(1000); + recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.H263, + MediaRecorder.OutputFormat.THREE_GPP, + MediaNames.RECORDED_PORTRAIT_H263, true); + videoRecordedResult = + validateVideo(MediaNames.RECORDED_PORTRAIT_H263, 352, 288); + mCamera.lock(); + mCamera.release(); + } catch (Exception e) { + Log.v(TAG, e.toString()); + } assertTrue("PortraitH263", videoRecordedResult); } diff --git a/opengl/java/android/opengl/GLES10.java b/opengl/java/android/opengl/GLES10.java index e597d12..147b60f 100644 --- a/opengl/java/android/opengl/GLES10.java +++ b/opengl/java/android/opengl/GLES10.java @@ -671,20 +671,9 @@ public class GLES10 { // C function const GLubyte * glGetString ( GLenum name ) - public native String _glGetString( + public static native String glGetString( int name ); - - public String glGetString( - int name - ) { - String returnValue; - returnValue = _glGetString( - name - ); - return returnValue; - } - // C function void glHint ( GLenum target, GLenum mode ) public static native void glHint( diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 3b4c041..c44478d 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -1,17 +1,17 @@ -/* +/* ** ** Copyright 2007 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 +** 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 +** 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 +** 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. */ @@ -478,22 +478,38 @@ struct extention_map_t { }; static const extention_map_t gExtentionMap[] = { - { "glDrawTexsOES", (void(*)())&glDrawTexsOES }, - { "glDrawTexiOES", (void(*)())&glDrawTexiOES }, - { "glDrawTexfOES", (void(*)())&glDrawTexfOES }, - { "glDrawTexxOES", (void(*)())&glDrawTexxOES }, - { "glDrawTexsvOES", (void(*)())&glDrawTexsvOES }, - { "glDrawTexivOES", (void(*)())&glDrawTexivOES }, - { "glDrawTexfvOES", (void(*)())&glDrawTexfvOES }, - { "glDrawTexxvOES", (void(*)())&glDrawTexxvOES }, - { "glQueryMatrixxOES", (void(*)())&glQueryMatrixxOES }, - { "glClipPlanef", (void(*)())&glClipPlanef }, - { "glClipPlanex", (void(*)())&glClipPlanex }, - { "glBindBuffer", (void(*)())&glBindBuffer }, - { "glBufferData", (void(*)())&glBufferData }, - { "glBufferSubData", (void(*)())&glBufferSubData }, - { "glDeleteBuffers", (void(*)())&glDeleteBuffers }, - { "glGenBuffers", (void(*)())&glGenBuffers }, + { "glDrawTexsOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES }, + { "glDrawTexiOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES }, + { "glDrawTexfOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES }, + { "glDrawTexxOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES }, + { "glDrawTexsvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES }, + { "glDrawTexivOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES }, + { "glDrawTexfvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES }, + { "glDrawTexxvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES }, + { "glQueryMatrixxOES", + (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES }, + { "glClipPlanef", + (__eglMustCastToProperFunctionPointerType)&glClipPlanef }, + { "glClipPlanex", + (__eglMustCastToProperFunctionPointerType)&glClipPlanex }, + { "glBindBuffer", + (__eglMustCastToProperFunctionPointerType)&glBindBuffer }, + { "glBufferData", + (__eglMustCastToProperFunctionPointerType)&glBufferData }, + { "glBufferSubData", + (__eglMustCastToProperFunctionPointerType)&glBufferSubData }, + { "glDeleteBuffers", + (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers }, + { "glGenBuffers", + (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, }; /* @@ -1299,6 +1315,8 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, } } + // TODO: call connect / disconnect on the surface + ogles_context_t* gl = (ogles_context_t*)ctx; if (makeCurrent(gl) == 0) { if (ctx) { diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk index 2ecc776..d636d73 100644 --- a/opengl/libs/Android.mk +++ b/opengl/libs/Android.mk @@ -35,7 +35,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ GLES_CM/gl.cpp.arm \ - GLES_CM/gl_logger.cpp \ # LOCAL_SHARED_LIBRARIES += libcutils libutils libui libEGL diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 0b4bcce..5ed3ecc 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -14,7 +14,7 @@ ** limitations under the License. */ -#define LOG_TAG "GLLogger" +#define LOG_TAG "libEGL" #include <ctype.h> #include <string.h> @@ -69,9 +69,9 @@ private: struct egl_display_t : public egl_object_t<'_dpy'> { - EGLDisplay dpys[2]; - EGLConfig* configs[2]; - EGLint numConfigs[2]; + EGLDisplay dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; + EGLConfig* configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; + EGLint numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; EGLint numTotalConfigs; char const* extensionsString; volatile int32_t refs; @@ -81,7 +81,7 @@ struct egl_display_t : public egl_object_t<'_dpy'> char const * clientApi; char const * extensions; }; - strings_t queryString[2]; + strings_t queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; }; struct egl_surface_t : public egl_object_t<'_srf'> @@ -143,6 +143,7 @@ static void gl_unimplemented() { static char const * const gl_names[] = { #include "gl_entries.in" + #include "glext_entries.in" NULL }; @@ -156,7 +157,7 @@ static char const * const egl_names[] = { // ---------------------------------------------------------------------------- -egl_connection_t gEGLImpl[2]; +egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; static egl_display_t gDisplay[NUM_DISPLAYS]; static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t gEGLThreadLocalStorageKey = -1; @@ -272,35 +273,81 @@ int gpu_release(void*, request_gpu_t* gpu); static __attribute__((noinline)) void *load_driver(const char* driver, gl_hooks_t* hooks) { + //LOGD("%s", driver); + char scrap[256]; void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL); LOGE_IF(!dso, "couldn't load <%s> library (%s)", driver, dlerror()); if (dso) { - void** curr; + // first find the symbol for eglGetProcAddress + + typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)( + const char*); + + getProcAddressType getProcAddress = + (getProcAddressType)dlsym(dso, "eglGetProcAddress"); + + LOGE_IF(!getProcAddress, + "can't find eglGetProcAddress() in %s", driver); + + __eglMustCastToProperFunctionPointerType* curr; char const * const * api; - gl_hooks_t::gl_t* gl = &hooks->gl; - curr = (void**)gl; - api = gl_names; + + gl_hooks_t::egl_t* egl = &hooks->egl; + curr = (__eglMustCastToProperFunctionPointerType*)egl; + api = egl_names; while (*api) { - void* f = dlsym(dso, *api); - //LOGD("<%s> @ 0x%p", *api, f); + char const * name = *api; + __eglMustCastToProperFunctionPointerType f = + (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); if (f == NULL) { - //LOGW("<%s> not found in %s", *api, driver); - f = (void*)gl_unimplemented; + // couldn't find the entry-point, use eglGetProcAddress() + f = getProcAddress(name); + if (f == NULL) { + f = (__eglMustCastToProperFunctionPointerType)0; + } } *curr++ = f; api++; } - gl_hooks_t::egl_t* egl = &hooks->egl; - curr = (void**)egl; - api = egl_names; + + gl_hooks_t::gl_t* gl = &hooks->gl; + curr = (__eglMustCastToProperFunctionPointerType*)gl; + api = gl_names; while (*api) { - void* f = dlsym(dso, *api); + char const * name = *api; + __eglMustCastToProperFunctionPointerType f = + (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); + if (f == NULL) { + // couldn't find the entry-point, use eglGetProcAddress() + f = getProcAddress(name); + } + if (f == NULL) { + // Try without the OES postfix + ssize_t index = ssize_t(strlen(name)) - 3; + if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) { + strncpy(scrap, name, index); + scrap[index] = 0; + f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); + //LOGD_IF(f, "found <%s> instead", scrap); + } + } + if (f == NULL) { + // Try with the OES postfix + ssize_t index = ssize_t(strlen(name)) - 3; + if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) { + strncpy(scrap, name, index); + scrap[index] = 0; + strcat(scrap, "OES"); + f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); + //LOGD_IF(f, "found <%s> instead", scrap); + } + } if (f == NULL) { - //LOGW("<%s> not found in %s", *api, driver); - f = (void*)0; + //LOGD("%s", name); + f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; } *curr++ = f; api++; @@ -429,18 +476,19 @@ egl_display_t* get_display(EGLDisplay dpy) return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index]; } +template<typename NATIVE, typename EGL> +static inline NATIVE* egl_to_native_cast(EGL arg) { + return reinterpret_cast<NATIVE*>(arg); +} + static inline -egl_surface_t* get_surface(EGLSurface surface) -{ - egl_surface_t* s = (egl_surface_t *)surface; - return s; +egl_surface_t* get_surface(EGLSurface surface) { + return egl_to_native_cast<egl_surface_t>(surface); } static inline -egl_context_t* get_context(EGLContext context) -{ - egl_context_t* c = (egl_context_t *)context; - return c; +egl_context_t* get_context(EGLContext context) { + return egl_to_native_cast<egl_context_t>(context); } static egl_connection_t* validate_display_config( @@ -451,7 +499,7 @@ static egl_connection_t* validate_display_config( if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL); impl = uintptr_t(config)>>24; - if (uint32_t(impl) >= 2) { + if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) { return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); } index = uintptr_t(config) & 0xFFFFFF; @@ -491,13 +539,8 @@ static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface) return EGL_TRUE; } -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- - -using namespace android; -EGLDisplay eglGetDisplay(NativeDisplayType display) +EGLDisplay egl_init_displays(NativeDisplayType display) { if (sEarlyInitState) { return EGL_NO_DISPLAY; @@ -510,7 +553,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU); egl_display_t* d = &gDisplay[index]; - + // dynamically load all our EGL implementations for that display // and call into the real eglGetGisplay() egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE]; @@ -573,6 +616,18 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) return dpy; } + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + +EGLDisplay eglGetDisplay(NativeDisplayType display) +{ + return egl_init_displays(display); +} + // ---------------------------------------------------------------------------- // Initialization // ---------------------------------------------------------------------------- @@ -594,7 +649,7 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) // build our own extension string first, based on the extension we know // and the extension supported by our client implementation dp->extensionsString = strdup(gExtensionString); - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; cnx->major = -1; cnx->minor = -1; @@ -624,7 +679,7 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) } EGLBoolean res = EGL_FALSE; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { EGLint n; @@ -663,7 +718,7 @@ EGLBoolean eglTerminate(EGLDisplay dpy) return EGL_TRUE; EGLBoolean res = EGL_FALSE; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { cnx->hooks->egl.eglTerminate(dp->dpys[i]); @@ -706,7 +761,7 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy, return EGL_TRUE; } GLint n = 0; - for (int j=0 ; j<2 ; j++) { + for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) { for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) { *configs++ = MAKE_CONFIG(j, i); config_size--; @@ -794,7 +849,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, return res; } - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglChooseConfig( @@ -1107,7 +1162,7 @@ EGLBoolean eglWaitNative(EGLint engine) EGLint eglGetError(void) { EGLint result = EGL_SUCCESS; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { EGLint err = EGL_SUCCESS; egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) @@ -1120,8 +1175,15 @@ EGLint eglGetError(void) return result; } -void (*eglGetProcAddress(const char *procname))() +__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) { + // eglGetProcAddress() could be the very first function called + // in which case we must make sure we've initialized ourselves, this + // happens the first time egl_get_display() is called. + + if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY) + return NULL; + __eglMustCastToProperFunctionPointerType addr; addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); if (addr) return addr; @@ -1133,7 +1195,7 @@ void (*eglGetProcAddress(const char *procname))() addr = 0; int slot = -1; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglGetProcAddress) { @@ -1266,7 +1328,7 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); EGLBoolean res = EGL_TRUE; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglSwapInterval) { @@ -1309,7 +1371,7 @@ EGLBoolean eglBindAPI(EGLenum api) { // bind this API on all EGLs EGLBoolean res = EGL_TRUE; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglBindAPI) { @@ -1324,7 +1386,7 @@ EGLBoolean eglBindAPI(EGLenum api) EGLenum eglQueryAPI(void) { - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglQueryAPI) { @@ -1340,7 +1402,7 @@ EGLenum eglQueryAPI(void) EGLBoolean eglReleaseThread(void) { - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglReleaseThread) { diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp index 865cf44..0057168 100644 --- a/opengl/libs/GLES_CM/gl.cpp +++ b/opengl/libs/GLES_CM/gl.cpp @@ -29,6 +29,7 @@ #include <cutils/properties.h> #include "hooks.h" +#include "egl_impl.h" using namespace android; @@ -57,13 +58,6 @@ void glVertexPointerBounds(GLint size, GLenum type, // Actual GL entry-points // ---------------------------------------------------------------------------- -#if GL_LOGGER -# include "gl_logger.h" -# define GL_LOGGER_IMPL(_x) _x -#else -# define GL_LOGGER_IMPL(_x) -#endif - #undef API_ENTRY #undef CALL_GL_API #undef CALL_GL_API_RETURN @@ -96,21 +90,36 @@ void glVertexPointerBounds(GLint size, GLenum type, #define CALL_GL_API(_api, ...) \ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ - GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); ) \ _c->_api(__VA_ARGS__) #define CALL_GL_API_RETURN(_api, ...) \ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ - GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); ) \ return _c->_api(__VA_ARGS__) #endif + extern "C" { #include "gl_api.in" +#include "glext_api.in" } #undef API_ENTRY #undef CALL_GL_API #undef CALL_GL_API_RETURN + +/* + * These GL calls are special because they need to call into EGL to retrieve + * some informations before they can execute. + */ + + +void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ +} + +void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ +} + diff --git a/opengl/libs/GLES_CM/gl_api.in b/opengl/libs/GLES_CM/gl_api.in index 9234ef2..5437d47 100644 --- a/opengl/libs/GLES_CM/gl_api.in +++ b/opengl/libs/GLES_CM/gl_api.in @@ -1,606 +1,435 @@ -void API_ENTRY(glActiveTexture)(GLenum texture) { - CALL_GL_API(glActiveTexture, texture); -} - void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) { CALL_GL_API(glAlphaFunc, func, ref); } - +void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + CALL_GL_API(glClearColor, red, green, blue, alpha); +} +void API_ENTRY(glClearDepthf)(GLclampf depth) { + CALL_GL_API(glClearDepthf, depth); +} +void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) { + CALL_GL_API(glClipPlanef, plane, equation); +} +void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + CALL_GL_API(glColor4f, red, green, blue, alpha); +} +void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) { + CALL_GL_API(glDepthRangef, zNear, zFar); +} +void API_ENTRY(glFogf)(GLenum pname, GLfloat param) { + CALL_GL_API(glFogf, pname, param); +} +void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glFogfv, pname, params); +} +void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) { + CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar); +} +void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) { + CALL_GL_API(glGetClipPlanef, pname, eqn); +} +void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) { + CALL_GL_API(glGetFloatv, pname, params); +} +void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetLightfv, light, pname, params); +} +void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetMaterialfv, face, pname, params); +} +void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetTexEnvfv, env, pname, params); +} +void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetTexParameterfv, target, pname, params); +} +void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) { + CALL_GL_API(glLightModelf, pname, param); +} +void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glLightModelfv, pname, params); +} +void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) { + CALL_GL_API(glLightf, light, pname, param); +} +void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) { + CALL_GL_API(glLightfv, light, pname, params); +} +void API_ENTRY(glLineWidth)(GLfloat width) { + CALL_GL_API(glLineWidth, width); +} +void API_ENTRY(glLoadMatrixf)(const GLfloat *m) { + CALL_GL_API(glLoadMatrixf, m); +} +void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) { + CALL_GL_API(glMaterialf, face, pname, param); +} +void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) { + CALL_GL_API(glMaterialfv, face, pname, params); +} +void API_ENTRY(glMultMatrixf)(const GLfloat *m) { + CALL_GL_API(glMultMatrixf, m); +} +void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { + CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q); +} +void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) { + CALL_GL_API(glNormal3f, nx, ny, nz); +} +void API_ENTRY(glOrthof)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) { + CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar); +} +void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) { + CALL_GL_API(glPointParameterf, pname, param); +} +void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) { + CALL_GL_API(glPointParameterfv, pname, params); +} +void API_ENTRY(glPointSize)(GLfloat size) { + CALL_GL_API(glPointSize, size); +} +void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) { + CALL_GL_API(glPolygonOffset, factor, units); +} +void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glRotatef, angle, x, y, z); +} +void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glScalef, x, y, z); +} +void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) { + CALL_GL_API(glTexEnvf, target, pname, param); +} +void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) { + CALL_GL_API(glTexEnvfv, target, pname, params); +} +void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) { + CALL_GL_API(glTexParameterf, target, pname, param); +} +void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) { + CALL_GL_API(glTexParameterfv, target, pname, params); +} +void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glTranslatef, x, y, z); +} +void API_ENTRY(glActiveTexture)(GLenum texture) { + CALL_GL_API(glActiveTexture, texture); +} void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) { CALL_GL_API(glAlphaFuncx, func, ref); } - +void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) { + CALL_GL_API(glBindBuffer, target, buffer); +} void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) { CALL_GL_API(glBindTexture, target, texture); } - void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) { CALL_GL_API(glBlendFunc, sfactor, dfactor); } - +void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) { + CALL_GL_API(glBufferData, target, size, data, usage); +} +void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) { + CALL_GL_API(glBufferSubData, target, offset, size, data); +} void API_ENTRY(glClear)(GLbitfield mask) { CALL_GL_API(glClear, mask); } - -void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { - CALL_GL_API(glClearColor, red, green, blue, alpha); -} - void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { CALL_GL_API(glClearColorx, red, green, blue, alpha); } - -void API_ENTRY(glClearDepthf)(GLclampf depth) { - CALL_GL_API(glClearDepthf, depth); -} - void API_ENTRY(glClearDepthx)(GLclampx depth) { CALL_GL_API(glClearDepthx, depth); } - void API_ENTRY(glClearStencil)(GLint s) { CALL_GL_API(glClearStencil, s); } - void API_ENTRY(glClientActiveTexture)(GLenum texture) { CALL_GL_API(glClientActiveTexture, texture); } - -void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - CALL_GL_API(glColor4f, red, green, blue, alpha); +void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) { + CALL_GL_API(glClipPlanex, plane, equation); +} +void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { + CALL_GL_API(glColor4ub, red, green, blue, alpha); } - void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) { CALL_GL_API(glColor4x, red, green, blue, alpha); } - -void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { - CALL_GL_API(glColorMask, r, g, b, a); -} - -void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) -{ - CALL_GL_API(glColorPointer, size, type, stride, ptr); -} - -void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLint border, - GLsizei imageSize, const GLvoid *data) { - CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, - width, height, border, imageSize, data); -} - -void API_ENTRY(glCompressedTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, - const GLvoid *data) { - CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, - width, height, format, imageSize, data); -} - -void API_ENTRY(glCopyTexImage2D)( GLenum target, GLint level, GLenum internalformat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border) { - CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, - width, height, border); -} - -void API_ENTRY(glCopyTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLint x, GLint y, GLsizei width, - GLsizei height) { - CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, - width, height); -} - +void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { + CALL_GL_API(glColorMask, red, green, blue, alpha); +} +void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glColorPointer, size, type, stride, pointer); +} +void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) { + CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data); +} +void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) { + CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data); +} +void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { + CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, width, height, border); +} +void API_ENTRY(glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, width, height); +} void API_ENTRY(glCullFace)(GLenum mode) { CALL_GL_API(glCullFace, mode); } - +void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint *buffers) { + CALL_GL_API(glDeleteBuffers, n, buffers); +} void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) { CALL_GL_API(glDeleteTextures, n, textures); } - void API_ENTRY(glDepthFunc)(GLenum func) { CALL_GL_API(glDepthFunc, func); } - void API_ENTRY(glDepthMask)(GLboolean flag) { CALL_GL_API(glDepthMask, flag); } - -void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) { - CALL_GL_API(glDepthRangef, zNear, zFar); -} - void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) { CALL_GL_API(glDepthRangex, zNear, zFar); } - void API_ENTRY(glDisable)(GLenum cap) { CALL_GL_API(glDisable, cap); } - void API_ENTRY(glDisableClientState)(GLenum array) { CALL_GL_API(glDisableClientState, array); } - void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) { CALL_GL_API(glDrawArrays, mode, first, count); } - -void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, - GLenum type, const GLvoid *indices) { +void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { CALL_GL_API(glDrawElements, mode, count, type, indices); } - void API_ENTRY(glEnable)(GLenum cap) { CALL_GL_API(glEnable, cap); } - void API_ENTRY(glEnableClientState)(GLenum array) { CALL_GL_API(glEnableClientState, array); } - void API_ENTRY(glFinish)(void) { CALL_GL_API(glFinish); } - void API_ENTRY(glFlush)(void) { CALL_GL_API(glFlush); } - -void API_ENTRY(glFogf)(GLenum pname, GLfloat param) { - CALL_GL_API(glFogf, pname, param); -} - -void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glFogfv, pname, params); -} - void API_ENTRY(glFogx)(GLenum pname, GLfixed param) { CALL_GL_API(glFogx, pname, param); } - void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) { CALL_GL_API(glFogxv, pname, params); } - void API_ENTRY(glFrontFace)(GLenum mode) { CALL_GL_API(glFrontFace, mode); } - -void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat zNear, GLfloat zFar) { - CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar); -} - -void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right, - GLfixed bottom, GLfixed top, - GLfixed zNear, GLfixed zFar) { +void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) { CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar); } - +void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) { + CALL_GL_API(glGetBooleanv, pname, params); +} +void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) { + CALL_GL_API(glGetBufferParameteriv, target, pname, params); +} +void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) { + CALL_GL_API(glGetClipPlanex, pname, eqn); +} +void API_ENTRY(glGenBuffers)(GLsizei n, GLuint *buffers) { + CALL_GL_API(glGenBuffers, n, buffers); +} void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) { CALL_GL_API(glGenTextures, n, textures); } - GLenum API_ENTRY(glGetError)(void) { CALL_GL_API_RETURN(glGetError); } - +void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) { + CALL_GL_API(glGetFixedv, pname, params); +} void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) { CALL_GL_API(glGetIntegerv, pname, params); } - +void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetLightxv, light, pname, params); +} +void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetMaterialxv, face, pname, params); +} +void API_ENTRY(glGetPointerv)(GLenum pname, void **params) { + CALL_GL_API(glGetPointerv, pname, params); +} const GLubyte * API_ENTRY(glGetString)(GLenum name) { CALL_GL_API_RETURN(glGetString, name); } - +void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) { + CALL_GL_API(glGetTexEnviv, env, pname, params); +} +void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexEnvxv, env, pname, params); +} +void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) { + CALL_GL_API(glGetTexParameteriv, target, pname, params); +} +void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexParameterxv, target, pname, params); +} void API_ENTRY(glHint)(GLenum target, GLenum mode) { CALL_GL_API(glHint, target, mode); } - -void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) { - CALL_GL_API(glLightModelf, pname, param); +GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) { + CALL_GL_API_RETURN(glIsBuffer, buffer); } - -void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glLightModelfv, pname, params); +GLboolean API_ENTRY(glIsEnabled)(GLenum cap) { + CALL_GL_API_RETURN(glIsEnabled, cap); +} +GLboolean API_ENTRY(glIsTexture)(GLuint texture) { + CALL_GL_API_RETURN(glIsTexture, texture); } - void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) { CALL_GL_API(glLightModelx, pname, param); } - void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) { CALL_GL_API(glLightModelxv, pname, params); } - -void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) { - CALL_GL_API(glLightf, light, pname, param); -} - -void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) { - CALL_GL_API(glLightfv, light, pname, params); -} - void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) { CALL_GL_API(glLightx, light, pname, param); } - void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) { CALL_GL_API(glLightxv, light, pname, params); } - -void API_ENTRY(glLineWidth)(GLfloat width) { - CALL_GL_API(glLineWidth, width); -} - void API_ENTRY(glLineWidthx)(GLfixed width) { CALL_GL_API(glLineWidthx, width); } - void API_ENTRY(glLoadIdentity)(void) { CALL_GL_API(glLoadIdentity); } - -void API_ENTRY(glLoadMatrixf)(const GLfloat *m) { - CALL_GL_API(glLoadMatrixf, m); -} - void API_ENTRY(glLoadMatrixx)(const GLfixed *m) { CALL_GL_API(glLoadMatrixx, m); } - void API_ENTRY(glLogicOp)(GLenum opcode) { CALL_GL_API(glLogicOp, opcode); } - -void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) { - CALL_GL_API(glMaterialf, face, pname, param); -} - -void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) { - CALL_GL_API(glMaterialfv, face, pname, params); -} - void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) { CALL_GL_API(glMaterialx, face, pname, param); } - void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) { CALL_GL_API(glMaterialxv, face, pname, params); } - void API_ENTRY(glMatrixMode)(GLenum mode) { CALL_GL_API(glMatrixMode, mode); } - -void API_ENTRY(glMultMatrixf)(const GLfloat *m) { - CALL_GL_API(glMultMatrixf, m); -} - void API_ENTRY(glMultMatrixx)(const GLfixed *m) { CALL_GL_API(glMultMatrixx, m); } - -void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { - CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q); -} - void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) { CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q); } - -void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) { - CALL_GL_API(glNormal3f, nx, ny, nz); -} - void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) { CALL_GL_API(glNormal3x, nx, ny, nz); } - void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) { CALL_GL_API(glNormalPointer, type, stride, pointer); } - -void API_ENTRY(glOrthof)( GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat zNear, GLfloat zFar) { - CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar); -} - -void API_ENTRY(glOrthox)( GLfixed left, GLfixed right, - GLfixed bottom, GLfixed top, - GLfixed zNear, GLfixed zFar) { +void API_ENTRY(glOrthox)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) { CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar); } - void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) { CALL_GL_API(glPixelStorei, pname, param); } - -void API_ENTRY(glPointSize)(GLfloat size) { - CALL_GL_API(glPointSize, size); +void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) { + CALL_GL_API(glPointParameterx, pname, param); +} +void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glPointParameterxv, pname, params); } - void API_ENTRY(glPointSizex)(GLfixed size) { CALL_GL_API(glPointSizex, size); } - -void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) { - CALL_GL_API(glPolygonOffset, factor, units); -} - void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) { CALL_GL_API(glPolygonOffsetx, factor, units); } - void API_ENTRY(glPopMatrix)(void) { CALL_GL_API(glPopMatrix); } - void API_ENTRY(glPushMatrix)(void) { CALL_GL_API(glPushMatrix); } - -void API_ENTRY(glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid *pixels) { +void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels); } - -void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glRotatef, angle, x, y, z); -} - void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) { CALL_GL_API(glRotatex, angle, x, y, z); } - void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) { CALL_GL_API(glSampleCoverage, value, invert); } - void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) { CALL_GL_API(glSampleCoveragex, value, invert); } - -void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glScalef, x, y, z); -} - void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) { CALL_GL_API(glScalex, x, y, z); } - void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) { CALL_GL_API(glScissor, x, y, width, height); } - void API_ENTRY(glShadeModel)(GLenum mode) { CALL_GL_API(glShadeModel, mode); } - void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) { CALL_GL_API(glStencilFunc, func, ref, mask); } - void API_ENTRY(glStencilMask)(GLuint mask) { CALL_GL_API(glStencilMask, mask); } - void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) { CALL_GL_API(glStencilOp, fail, zfail, zpass); } - -void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { +void API_ENTRY(glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { CALL_GL_API(glTexCoordPointer, size, type, stride, pointer); } - -void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) { - CALL_GL_API(glTexEnvf, target, pname, param); -} - -void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) { - CALL_GL_API(glTexEnvfv, target, pname, params); +void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) { + CALL_GL_API(glTexEnvi, target, pname, param); } - void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) { CALL_GL_API(glTexEnvx, target, pname, param); } - +void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) { + CALL_GL_API(glTexEnviv, target, pname, params); +} void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) { CALL_GL_API(glTexEnvxv, target, pname, params); } - -void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLint border, GLenum format, - GLenum type, const GLvoid *pixels) { - CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, - border, format, type, pixels); +void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { + CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels); } - -void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) { - CALL_GL_API(glTexParameterf, target, pname, param); +void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) { + CALL_GL_API(glTexParameteri, target, pname, param); } - void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) { CALL_GL_API(glTexParameterx, target, pname, param); } - -void API_ENTRY(glTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid *pixels) { - CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, - width, height, format, type, pixels); +void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) { + CALL_GL_API(glTexParameteriv, target, pname, params); } - -void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glTranslatef, x, y, z); +void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) { + CALL_GL_API(glTexParameterxv, target, pname, params); +} +void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) { + CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels); } - void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) { CALL_GL_API(glTranslatex, x, y, z); } - -void API_ENTRY(glVertexPointer)( GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { +void API_ENTRY(glVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { CALL_GL_API(glVertexPointer, size, type, stride, pointer); } - void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) { CALL_GL_API(glViewport, x, y, width, height); } - -// ES 1.1 -void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) { - CALL_GL_API(glClipPlanef, plane, equation); -} -void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) { - CALL_GL_API(glClipPlanex, plane, equation); -} -void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) { - CALL_GL_API(glBindBuffer, target, buffer); -} -void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { - CALL_GL_API(glBufferData, target, size, data, usage); -} -void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { - CALL_GL_API(glBufferSubData, target, offset, size, data); -} -void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) { - CALL_GL_API(glDeleteBuffers, n, buffers); -} -void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) { - CALL_GL_API(glGenBuffers, n, buffers); -} -void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) { - CALL_GL_API(glGetBooleanv, pname, params); -} -void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) { - CALL_GL_API(glGetFixedv, pname, params); -} -void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) { - CALL_GL_API(glGetFloatv, pname, params); -} -void API_ENTRY(glGetPointerv)(GLenum pname, void **params) { - CALL_GL_API(glGetPointerv, pname, params); -} -void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) { - CALL_GL_API(glGetBufferParameteriv, target, pname, params); -} -void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) { - CALL_GL_API(glGetClipPlanef, pname, eqn); -} -void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) { - CALL_GL_API(glGetClipPlanex, pname, eqn); -} -void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetLightxv, light, pname, params); -} -void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetLightfv, light, pname, params); -} -void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetMaterialxv, face, pname, params); -} -void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetMaterialfv, face, pname, params); -} -void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetTexEnvfv, env, pname, params); -} -void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) { - CALL_GL_API(glGetTexEnviv, env, pname, params); -} -void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetTexEnvxv, env, pname, params); -} -void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetTexParameterfv, target, pname, params); -} -void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) { - CALL_GL_API(glGetTexParameteriv, target, pname, params); -} -void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetTexParameterxv, target, pname, params); -} -GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) { - CALL_GL_API_RETURN(glIsBuffer, buffer); -} -GLboolean API_ENTRY(glIsEnabled)(GLenum cap) { - CALL_GL_API_RETURN(glIsEnabled, cap); -} -GLboolean API_ENTRY(glIsTexture)(GLuint texture) { - CALL_GL_API_RETURN(glIsTexture, texture); -} -void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) { - CALL_GL_API(glPointParameterf, pname, param); -} -void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glPointParameterfv, pname, params); -} -void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) { - CALL_GL_API(glPointParameterx, pname, param); -} -void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) { - CALL_GL_API(glPointParameterxv, pname, params); -} -void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { - CALL_GL_API(glColor4ub, red, green, blue, alpha); -} -void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) { - CALL_GL_API(glTexEnvi, target, pname, param); -} -void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) { - CALL_GL_API(glTexEnviv, target, pname, params); -} - -void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) { - CALL_GL_API(glTexParameterfv, target, pname, params); -} - -void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) { - CALL_GL_API(glTexParameteriv, target, pname, params); -} - -void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) { - CALL_GL_API(glTexParameteri, target, pname, param); -} -void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) { - CALL_GL_API(glTexParameterxv, target, pname, params); -} void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) { CALL_GL_API(glPointSizePointerOES, type, stride, pointer); } - -// Extensions -void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { - CALL_GL_API(glDrawTexsOES, x, y, z, w, h); -} -void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) { - CALL_GL_API(glDrawTexiOES, x, y, z, w, h); -} -void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) { - CALL_GL_API(glDrawTexfOES, x, y, z, w, h); -} -void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { - CALL_GL_API(glDrawTexxOES, x, y, z, w, h); -} -void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) { - CALL_GL_API(glDrawTexsvOES, coords); -} -void API_ENTRY(glDrawTexivOES)(const GLint* coords) { - CALL_GL_API(glDrawTexivOES, coords); -} -void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) { - CALL_GL_API(glDrawTexfvOES, coords); -} -void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) { - CALL_GL_API(glDrawTexxvOES, coords); -} -GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) { - CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent); -} diff --git a/opengl/libs/GLES_CM/gl_logger.cpp b/opengl/libs/GLES_CM/gl_logger.cpp deleted file mode 100644 index 27be5c9..0000000 --- a/opengl/libs/GLES_CM/gl_logger.cpp +++ /dev/null @@ -1,1060 +0,0 @@ -/* - ** Copyright 2007, 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. - */ - -#define LOG_TAG "GLLogger" - -#include <ctype.h> -#include <string.h> -#include <errno.h> -#include <dlfcn.h> - -#include <sys/ioctl.h> - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES/gl.h> -#include <GLES/glext.h> - -#include <cutils/log.h> -#include <cutils/atomic.h> -#include <cutils/properties.h> - -#include <utils/String8.h> - -#include "gl_logger.h" - -#undef NELEM -#define NELEM(x) (sizeof(x)/sizeof(*(x))) - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -template<typename T> -static int binarySearch(T const sortedArray[], int first, int last, EGLint key) -{ - while (first <= last) { - int mid = (first + last) / 2; - if (key > sortedArray[mid].key) { - first = mid + 1; - } else if (key < sortedArray[mid].key) { - last = mid - 1; - } else { - return mid; - } - } - return -1; -} - -struct pair_t { - const char* name; - int key; -}; - -static const pair_t gEnumMap[] = { - #define GLENUM(NAME, VALUE) { #NAME, VALUE }, - #include "gl_enums.in" - #undef GLENUM -}; - -// ---------------------------------------------------------------------------- - -template<typename TYPE> -class GLLogValue { -public: - GLLogValue(TYPE value) : mValue(value) { } - const TYPE& getValue() const { return mValue; } - String8 toString() const { - return convertToString(mValue); - } -private: - const TYPE& mValue; - String8 convertToString(unsigned int v) const { - char buf[16]; - snprintf(buf, 16, "%u", v); - return String8(buf); - } - String8 convertToString(unsigned long v) const { - char buf[16]; - snprintf(buf, 16, "%lu", v); - return String8(buf); - } - String8 convertToString(int v) const { - char buf[16]; - snprintf(buf, 16, "%d", v); - return String8(buf); - } - String8 convertToString(long v) const { - char buf[16]; - snprintf(buf, 16, "%ld", v); - return String8(buf); - } - String8 convertToString(float v) const { - char buf[16]; - snprintf(buf, 16, "%f", v); - return String8(buf); - } - String8 convertToString(void const* v) const { - char buf[16]; - snprintf(buf, 16, "%p", v); - return String8(buf); - } -}; - -class GLLogEnum : public GLLogValue<GLenum> { -public: - GLLogEnum(GLenum v) : GLLogValue<GLenum>(v) { } - String8 toString() const { - GLenum v = getValue(); - int i = binarySearch<pair_t>(gEnumMap, 0, NELEM(gEnumMap)-1, v); - if (i >= 0) { - return String8(gEnumMap[i].name); - } else { - char buf[16]; - snprintf(buf, 16, "0x%04x", v); - return String8(buf); - } - } -}; - -class GLLogClearBitfield : public GLLogValue<GLbitfield> { -public: - GLLogClearBitfield(GLbitfield v) : GLLogValue<GLbitfield>(v) { } - String8 toString() const { - char buf[16]; - snprintf(buf, 16, "0x%08x", getValue()); - return String8(buf); - } -}; - -class GLLogBool : public GLLogValue<GLboolean> { -public: - GLLogBool(GLboolean v) : GLLogValue<GLboolean>(v) { } - String8 toString() const { - GLboolean v = getValue(); - if (v == GL_TRUE) return String8("GL_TRUE"); - if (v == GL_FALSE) return String8("GL_FALSE"); - return GLLogValue<GLboolean>::toString(); - } -}; - -class GLLogFixed : public GLLogValue<GLfixed> { -public: - GLLogFixed(GLfixed v) : GLLogValue<GLfixed>(v) { } - String8 toString() const { - char buf[16]; - snprintf(buf, 16, "0x%08x", getValue()); - return String8(buf); - } -}; - - -template <typename TYPE> -class GLLogBuffer : public GLLogValue<TYPE *> { -public: - GLLogBuffer(TYPE* buffer, size_t count = -1) - : GLLogValue<TYPE*>(buffer) - { // output buffer - } - GLLogBuffer(TYPE const* buffer, size_t count = -1) - : GLLogValue<TYPE*>(const_cast<TYPE*>(buffer)) - { // input buffer - } -}; - -class GLLog -{ -public: - GLLog(const char* name) : mNumParams(0) { - mString.append(name); - mString.append("("); - } - - ~GLLog() { - LOGD("%s);", mString.string()); - } - - GLLog& operator << (unsigned char v) { - return *this << GLLogValue<unsigned int>(v); - } - GLLog& operator << (short v) { - return *this << GLLogValue<unsigned int>(v); - } - GLLog& operator << (unsigned int v) { - return *this << GLLogValue<unsigned int>(v); - } - GLLog& operator << (int v) { - return *this << GLLogValue<int>(v); - } - GLLog& operator << (long v) { - return *this << GLLogValue<long>(v); - } - GLLog& operator << (unsigned long v) { - return *this << GLLogValue<unsigned long>(v); - } - GLLog& operator << (float v) { - return *this << GLLogValue<float>(v); - } - GLLog& operator << (const void* v) { - return *this << GLLogValue<const void* >(v); - } - - template <typename TYPE> - GLLog& operator << (const TYPE& rhs) { - if (mNumParams > 0) - mString.append(", "); - mString.append(rhs.toString()); - mNumParams++; - return *this; - } - - const String8& string() const { return mString; } -private: - GLLog(const GLLog&); - - String8 mString; - int mNumParams; -}; - -#define API_ENTRY(api) log_##api -#define CALL_GL_API(_x, ...) -#define CALL_GL_API_RETURN(_x, ...) return(0); - -void API_ENTRY(glActiveTexture)(GLenum texture) { - CALL_GL_API(glActiveTexture, texture); - GLLog("glActiveTexture") << GLLogEnum(texture); -} - -void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) { - CALL_GL_API(glAlphaFunc, func, ref); - GLLog("glAlphaFunc") << GLLogEnum(func) << ref; -} - -void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) { - CALL_GL_API(glAlphaFuncx, func, ref); - GLLog("glAlphaFuncx") << GLLogEnum(func) << GLLogFixed(ref); -} - -void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) { - CALL_GL_API(glBindTexture, target, texture); - GLLog("glBindTexture") << GLLogEnum(target) << texture; -} - -void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) { - CALL_GL_API(glBlendFunc, sfactor, dfactor); - GLLog("glBlendFunc") << GLLogEnum(sfactor) << GLLogEnum(dfactor); -} - -void API_ENTRY(glClear)(GLbitfield mask) { - CALL_GL_API(glClear, mask); - GLLog("glClear") << GLLogClearBitfield(mask); -} - -void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { - CALL_GL_API(glClearColor, red, green, blue, alpha); - GLLog("glClearColor") << red << green << blue << alpha; -} - -void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { - CALL_GL_API(glClearColorx, red, green, blue, alpha); - GLLog("glClearColorx") << GLLogFixed(red) << GLLogFixed(green) << GLLogFixed(blue) << GLLogFixed(alpha); -} - -void API_ENTRY(glClearDepthf)(GLclampf depth) { - CALL_GL_API(glClearDepthf, depth); - GLLog("glClearDepthf") << depth; -} - -void API_ENTRY(glClearDepthx)(GLclampx depth) { - CALL_GL_API(glClearDepthx, depth); - GLLog("glClearDepthx") << GLLogFixed(depth); -} - -void API_ENTRY(glClearStencil)(GLint s) { - CALL_GL_API(glClearStencil, s); - GLLog("glClearStencil") << s; -} - -void API_ENTRY(glClientActiveTexture)(GLenum texture) { - CALL_GL_API(glClientActiveTexture, texture); - GLLog("glClientActiveTexture") << GLLogEnum(texture); -} - -void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - CALL_GL_API(glColor4f, red, green, blue, alpha); - GLLog("glColor4f") << red << green << blue << alpha; -} - -void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) { - CALL_GL_API(glColor4x, red, green, blue, alpha); - GLLog("glColor4x") << GLLogFixed(red) << GLLogFixed(green) << GLLogFixed(blue) << GLLogFixed(alpha); -} - -void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { - CALL_GL_API(glColorMask, r, g, b, a); - GLLog("glColorMask") << GLLogBool(r) << GLLogBool(g) << GLLogBool(b) << GLLogBool(a); -} - -void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) -{ - CALL_GL_API(glColorPointer, size, type, stride, ptr); - GLLog("glColorPointer") << size << GLLogEnum(type) << stride << ptr; -} - -void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLint border, - GLsizei imageSize, const GLvoid *data) { - CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, - width, height, border, imageSize, data); - GLLog("glCompressedTexImage2D") - << GLLogEnum(target) << level << GLLogEnum(internalformat) - << width << height << border << imageSize << data; -} - -void API_ENTRY(glCompressedTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, - const GLvoid *data) { - CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, - width, height, format, imageSize, data); - GLLog("glCompressedTexSubImage2D") - << GLLogEnum(target) << level << xoffset << yoffset - << width << height << GLLogEnum(format) << imageSize << data; -} - -void API_ENTRY(glCopyTexImage2D)( GLenum target, GLint level, GLenum internalformat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border) { - CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, - width, height, border); - GLLog("glCopyTexImage2D") - << GLLogEnum(target) << level << GLLogEnum(internalformat) - << x << y << width << height << border; -} - -void API_ENTRY(glCopyTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLint x, GLint y, GLsizei width, - GLsizei height) { - CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, - width, height); - GLLog("glCopyTexSubImage2D") - << GLLogEnum(target) << level << xoffset << yoffset - << x << y << width << height; -} - -void API_ENTRY(glCullFace)(GLenum mode) { - CALL_GL_API(glCullFace, mode); - GLLog("glCullFace") << GLLogEnum(mode); -} - -void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) { - CALL_GL_API(glDeleteTextures, n, textures); - GLLog("glDeleteTextures") << n << GLLogBuffer<GLuint>(textures, n); -} - -void API_ENTRY(glDepthFunc)(GLenum func) { - CALL_GL_API(glDepthFunc, func); - GLLog("glDepthFunc") << GLLogEnum(func); -} - -void API_ENTRY(glDepthMask)(GLboolean flag) { - CALL_GL_API(glDepthMask, flag); - GLLog("glDepthMask") << GLLogBool(flag); -} - -void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) { - CALL_GL_API(glDepthRangef, zNear, zFar); - GLLog("glDepthRangef") << zNear << zFar; -} - -void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) { - CALL_GL_API(glDepthRangex, zNear, zFar); - GLLog("glDepthRangex") << GLLogFixed(zNear) << GLLogFixed(zFar); -} - -void API_ENTRY(glDisable)(GLenum cap) { - CALL_GL_API(glDisable, cap); - GLLog("glDisable") << GLLogEnum(cap); -} - -void API_ENTRY(glDisableClientState)(GLenum array) { - CALL_GL_API(glDisableClientState, array); - GLLog("glDisableClientState") << GLLogEnum(array); -} - -void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) { - CALL_GL_API(glDrawArrays, mode, first, count); - GLLog("glDrawArrays") << GLLogEnum(mode) << first << count; -} - -void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, - GLenum type, const GLvoid *indices) { - CALL_GL_API(glDrawElements, mode, count, type, indices); - GLLog log("glDrawElements"); - log << GLLogEnum(mode) << count << GLLogEnum(type); - if (type == GL_UNSIGNED_BYTE) { - log << GLLogBuffer<GLubyte>(static_cast<const GLubyte*>(indices), count); - } else { - log << GLLogBuffer<GLushort>(static_cast<const GLushort*>(indices), count); - } - log; -} - -void API_ENTRY(glEnable)(GLenum cap) { - CALL_GL_API(glEnable, cap); - GLLog("glEnable") << GLLogEnum(cap); -} - -void API_ENTRY(glEnableClientState)(GLenum array) { - CALL_GL_API(glEnableClientState, array); - GLLog("glEnableClientState") << GLLogEnum(array); -} - -void API_ENTRY(glFinish)(void) { - CALL_GL_API(glFinish); - GLLog("glFinish"); -} - -void API_ENTRY(glFlush)(void) { - CALL_GL_API(glFlush); - GLLog("glFlush"); -} - -void API_ENTRY(glFogf)(GLenum pname, GLfloat param) { - CALL_GL_API(glFogf, pname, param); - GLLog("glFogf") << GLLogEnum(pname) << param; -} - -void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glFogfv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glFogfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} - -void API_ENTRY(glFogx)(GLenum pname, GLfixed param) { - CALL_GL_API(glFogx, pname, param); - GLLog("glFogx") << GLLogEnum(pname) << GLLogFixed(param); -} - -void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) { - CALL_GL_API(glFogxv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glFogfx") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} - -void API_ENTRY(glFrontFace)(GLenum mode) { - CALL_GL_API(glFrontFace, mode); - GLLog("glFrontFace") << GLLogEnum(mode); - } - -void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat zNear, GLfloat zFar) { - CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar); - GLLog("glFrustumf") << left << right << bottom << top << zNear << zFar; -} - -void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right, - GLfixed bottom, GLfixed top, - GLfixed zNear, GLfixed zFar) { - CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar); - GLLog("glFrustumx") - << GLLogFixed(left) << GLLogFixed(right) - << GLLogFixed(bottom) << GLLogFixed(top) - << GLLogFixed(zNear) << GLLogFixed(zFar); -} - -void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) { - CALL_GL_API(glGenTextures, n, textures); - GLLog("glGenTextures") << n << GLLogBuffer<GLuint>(textures, n); -} - -GLenum API_ENTRY(glGetError)(void) { - GLLog("glGetError"); - CALL_GL_API_RETURN(glGetError); -} - -void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) { - CALL_GL_API(glGetIntegerv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetIntegerv") << GLLogEnum(pname) << GLLogBuffer<GLint>(params); -} - -const GLubyte * API_ENTRY(glGetString)(GLenum name) { - GLLog("glGetString") << GLLogEnum(name); - CALL_GL_API_RETURN(glGetString, name); -} - -void API_ENTRY(glHint)(GLenum target, GLenum mode) { - CALL_GL_API(glHint, target, mode); - GLLog("GLenum") << GLLogEnum(target) << GLLogEnum(mode); -} - -void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) { - CALL_GL_API(glLightModelf, pname, param); - GLLog("glLightModelf") << GLLogEnum(pname) << param; -} - -void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glLightModelfv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glLightModelfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} - -void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) { - CALL_GL_API(glLightModelx, pname, param); - GLLog("glLightModelx") << GLLogEnum(pname) << GLLogFixed(param); -} - -void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) { - CALL_GL_API(glLightModelxv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glLightModelxv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} - -void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) { - CALL_GL_API(glLightf, light, pname, param); - GLLog("glLightf") << GLLogEnum(light) << GLLogEnum(pname) << param; -} - -void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) { - CALL_GL_API(glLightfv, light, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glLightfv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} - -void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) { - CALL_GL_API(glLightx, light, pname, param); - GLLog("glLightx") << GLLogEnum(light) << GLLogEnum(pname) << GLLogFixed(param); -} - -void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) { - CALL_GL_API(glLightxv, light, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glLightxv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} - -void API_ENTRY(glLineWidth)(GLfloat width) { - CALL_GL_API(glLineWidth, width); - GLLog("glLineWidth") << width; -} - -void API_ENTRY(glLineWidthx)(GLfixed width) { - CALL_GL_API(glLineWidthx, width); - GLLog("glLineWidth") << GLLogFixed(width); -} - -void API_ENTRY(glLoadIdentity)(void) { - CALL_GL_API(glLoadIdentity); - GLLog("glLoadIdentity"); -} - -void API_ENTRY(glLoadMatrixf)(const GLfloat *m) { - CALL_GL_API(glLoadMatrixf, m); - GLLog("glLoadMatrixf") << GLLogBuffer<GLfloat>(m, 16); -} - -void API_ENTRY(glLoadMatrixx)(const GLfixed *m) { - CALL_GL_API(glLoadMatrixx, m); - GLLog("glLoadMatrixx") << GLLogBuffer<GLfixed>(m, 16); -} - -void API_ENTRY(glLogicOp)(GLenum opcode) { - CALL_GL_API(glLogicOp, opcode); - GLLog("glLogicOp") << GLLogEnum(opcode); -} - -void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) { - CALL_GL_API(glMaterialf, face, pname, param); - GLLog("glMaterialf") << GLLogEnum(face) << GLLogEnum(pname) << param; -} - -void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) { - CALL_GL_API(glMaterialfv, face, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glMaterialfv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} - -void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) { - CALL_GL_API(glMaterialx, face, pname, param); - GLLog("glMaterialx") << GLLogEnum(face) << GLLogEnum(pname) << GLLogFixed(param); -} - -void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) { - CALL_GL_API(glMaterialxv, face, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glMaterialxv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} - -void API_ENTRY(glMatrixMode)(GLenum mode) { - CALL_GL_API(glMatrixMode, mode); - GLLog("glMatrixMode") << GLLogEnum(mode); -} - -void API_ENTRY(glMultMatrixf)(const GLfloat *m) { - CALL_GL_API(glMultMatrixf, m); - GLLog("glMultMatrixf") << GLLogBuffer<GLfloat>(m, 16); -} - -void API_ENTRY(glMultMatrixx)(const GLfixed *m) { - CALL_GL_API(glMultMatrixx, m); - GLLog("glMultMatrixx") << GLLogBuffer<GLfixed>(m, 16); -} - -void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { - CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q); - GLLog("glMultiTexCoord4f") << GLLogEnum(target) << s << t << r << q; -} - -void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) { - CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q); - GLLog("glMultiTexCoord4x") << GLLogEnum(target) - << GLLogFixed(s) << GLLogFixed(t) << GLLogFixed(r) << GLLogFixed(q); -} - -void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) { - CALL_GL_API(glNormal3f, nx, ny, nz); - GLLog("glNormal3f") << nx << ny << nz; -} - -void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) { - CALL_GL_API(glNormal3x, nx, ny, nz); - GLLog("glNormal3x") << GLLogFixed(nx) << GLLogFixed(ny) << GLLogFixed(nz); -} - -void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) { - CALL_GL_API(glNormalPointer, type, stride, pointer); - GLLog("glNormalPointer") << GLLogEnum(type) << stride << pointer; -} - -void API_ENTRY(glOrthof)( GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat zNear, GLfloat zFar) { - CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar); - GLLog("glOrthof") << left << right << bottom << top << zNear << zFar; -} - -void API_ENTRY(glOrthox)( GLfixed left, GLfixed right, - GLfixed bottom, GLfixed top, - GLfixed zNear, GLfixed zFar) { - CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar); - GLLog("glOrthox") << GLLogFixed(left) << GLLogFixed(right) - << GLLogFixed(bottom) << GLLogFixed(top) - << GLLogFixed(zNear) << GLLogFixed(zFar); -} - -void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) { - CALL_GL_API(glPixelStorei, pname, param); - GLLog("glPixelStorei") << GLLogEnum(pname) << param; -} - -void API_ENTRY(glPointSize)(GLfloat size) { - CALL_GL_API(glPointSize, size); - GLLog("glPointSize") << size; -} - -void API_ENTRY(glPointSizex)(GLfixed size) { - CALL_GL_API(glPointSizex, size); - GLLog("glPointSizex") << GLLogFixed(size); -} - -void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) { - CALL_GL_API(glPolygonOffset, factor, units); - GLLog("glPolygonOffset") << factor << units; -} - -void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) { - CALL_GL_API(glPolygonOffsetx, factor, units); - GLLog("glPolygonOffsetx") << GLLogFixed(factor) << GLLogFixed(units); -} - -void API_ENTRY(glPopMatrix)(void) { - CALL_GL_API(glPopMatrix); - GLLog("glPopMatrix"); -} - -void API_ENTRY(glPushMatrix)(void) { - CALL_GL_API(glPushMatrix); - GLLog("glPushMatrix"); -} - -void API_ENTRY(glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid *pixels) { - CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels); - // XXX: we need to compute the size of this buffer - GLLog("glReadPixels") << x << y << width << height << GLLogEnum(format) << GLLogEnum(type) - << GLLogBuffer<unsigned char>(static_cast<unsigned char *>(pixels)); -} - -void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glRotatef, angle, x, y, z); - GLLog("glRotatef") << angle << x << y << z; -} - -void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) { - CALL_GL_API(glRotatex, angle, x, y, z); - GLLog("glRotatex") << GLLogFixed(angle) << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z); -} - -void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) { - CALL_GL_API(glSampleCoverage, value, invert); - GLLog("glSampleCoverage") << value << GLLogBool(invert); -} - -void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) { - CALL_GL_API(glSampleCoveragex, value, invert); - GLLog("glSampleCoveragex") << GLLogFixed(value) << GLLogBool(invert); -} - -void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glScalef, x, y, z); - GLLog("glScalef") << x << y << z; -} - -void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) { - CALL_GL_API(glScalex, x, y, z); - GLLog("glScalex") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z); -} - -void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) { - CALL_GL_API(glScissor, x, y, width, height); - GLLog("glScissor") << x << y << width << height; -} - -void API_ENTRY(glShadeModel)(GLenum mode) { - CALL_GL_API(glShadeModel, mode); - GLLog("glShadeModel") << GLLogEnum(mode); -} - -void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) { - CALL_GL_API(glStencilFunc, func, ref, mask); - GLLog("glStencilFunc") << GLLogEnum(func) << ref << mask; -} - -void API_ENTRY(glStencilMask)(GLuint mask) { - CALL_GL_API(glStencilMask, mask); - GLLog("glStencilMask") << mask; -} - -void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) { - CALL_GL_API(glStencilOp, fail, zfail, zpass); - GLLog("glStencilOp") << GLLogEnum(fail) << GLLogEnum(zfail) << GLLogEnum(zpass); -} - -void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { - CALL_GL_API(glTexCoordPointer, size, type, stride, pointer); - GLLog("glTexCoordPointer") << size << GLLogEnum(type) << stride << pointer; -} - -void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) { - CALL_GL_API(glTexEnvf, target, pname, param); - GLLog("glTexEnvf") << GLLogEnum(target) << GLLogEnum(pname) << param; -} - -void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) { - CALL_GL_API(glTexEnvfv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glTexEnvx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} - -void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) { - CALL_GL_API(glTexEnvx, target, pname, param); - GLLog("glTexEnvx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogFixed(param); -} - -void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) { - CALL_GL_API(glTexEnvxv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glTexEnvxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} - -void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLint border, GLenum format, - GLenum type, const GLvoid *pixels) { - CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, - border, format, type, pixels); - GLLog("glTexImage2D") << GLLogEnum(target) << level << GLLogEnum(internalformat) - << width << height << border << GLLogEnum(format) << GLLogEnum(type) - << GLLogBuffer<unsigned char>( static_cast<const unsigned char *>(pixels)); -} - -void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) { - CALL_GL_API(glTexParameterf, target, pname, param); - GLLog("glTexParameterf") << GLLogEnum(target) << GLLogEnum(pname) << param; -} - -void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) { - CALL_GL_API(glTexParameterx, target, pname, param); - GLLog("glTexParameterx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogFixed(param); -} - -void API_ENTRY(glTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid *pixels) { - CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, - width, height, format, type, pixels); - GLLog("glTexSubImage2D") << GLLogEnum(target) << level << xoffset << yoffset - << width << height << GLLogEnum(format) << GLLogEnum(type) - << GLLogBuffer<unsigned char>( static_cast<const unsigned char *>(pixels)); -} - -void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glTranslatef, x, y, z); - GLLog("glTranslatef") << x << y << z; -} - -void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) { - CALL_GL_API(glTranslatex, x, y, z); - GLLog("glTranslatex") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z); -} - -void API_ENTRY(glVertexPointer)( GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { - CALL_GL_API(glVertexPointer, size, type, stride, pointer); - GLLog("glVertexPointer") << size << GLLogEnum(type) << stride << pointer; -} - -void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) { - CALL_GL_API(glViewport, x, y, width, height); - GLLog("glViewport") << x << y << width << height; -} - -// ES 1.1 -void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) { - CALL_GL_API(glClipPlanef, plane, equation); - GLLog("glClipPlanef") << GLLogEnum(plane) << GLLogBuffer<GLfloat>(equation, 4); -} -void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) { - CALL_GL_API(glClipPlanex, plane, equation); - GLLog("glClipPlanex") << GLLogEnum(plane) << GLLogBuffer<GLfixed>(equation, 4); -} -void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) { - CALL_GL_API(glBindBuffer, target, buffer); - GLLog("glBindBuffer") << GLLogEnum(target) << buffer; -} -void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { - CALL_GL_API(glBufferData, target, size, data, usage); - GLLog("glBufferData") << GLLogEnum(target) << size - << GLLogBuffer<unsigned char>(static_cast<const unsigned char*>(data), size); -} -void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { - CALL_GL_API(glBufferSubData, target, offset, size, data); - GLLog("glBufferSubData") << GLLogEnum(target) << offset << size - << GLLogBuffer<unsigned char>(static_cast<const unsigned char*>(data), size); -} -void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) { - CALL_GL_API(glDeleteBuffers, n, buffers); - GLLog("glDeleteBuffers") << n << GLLogBuffer<GLuint>(buffers, n); -} -void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) { - CALL_GL_API(glGenBuffers, n, buffers); - GLLog("glGenBuffers") << n << GLLogBuffer<GLuint>(buffers, n); -} -void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) { - CALL_GL_API(glGetBooleanv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetBooleanv") << GLLogEnum(pname) << GLLogBuffer<GLboolean>(params); -} -void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) { - CALL_GL_API(glGetFixedv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetFixedv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} -void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) { - CALL_GL_API(glGetFloatv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetFloatv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} -void API_ENTRY(glGetPointerv)(GLenum pname, void **params) { - CALL_GL_API(glGetPointerv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetPointerv") << GLLogEnum(pname) << GLLogBuffer<void*>(params); -} -void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) { - // XXX: we need to compute the size of this buffer - CALL_GL_API(glGetBufferParameteriv, target, pname, params); - GLLog("glGetBufferParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); -} -void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) { - CALL_GL_API(glGetClipPlanef, pname, eqn); - GLLog("glGetClipPlanef") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(eqn, 4); -} -void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) { - CALL_GL_API(glGetClipPlanex, pname, eqn); - GLLog("glGetClipPlanex") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(eqn, 4); -} -void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetLightxv, light, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetLightxv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} -void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetLightfv, light, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetLightfv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} -void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetMaterialxv, face, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetMaterialxv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} -void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetMaterialfv, face, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetMaterialfv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} -void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetTexEnvfv, env, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetTexEnvfv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} -void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) { - CALL_GL_API(glGetTexEnviv, env, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetTexEnviv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); -} -void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetTexEnvxv, env, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetTexEnvxv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} -void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetTexParameterfv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetTexParameterfv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} -void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) { - CALL_GL_API(glGetTexParameteriv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetTexParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); -} -void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetTexParameterxv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glGetTexParameterxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} -GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) { - GLLog("glIsBuffer") << buffer; - CALL_GL_API_RETURN(glIsBuffer, buffer); -} -GLboolean API_ENTRY(glIsEnabled)(GLenum cap) { - GLLog("glIsEnabled") << GLLogEnum(cap); - CALL_GL_API_RETURN(glIsEnabled, cap); -} -GLboolean API_ENTRY(glIsTexture)(GLuint texture) { - GLLog("glIsTexture") << texture; - CALL_GL_API_RETURN(glIsTexture, texture); -} -void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) { - CALL_GL_API(glPointParameterf, pname, param); - GLLog("glPointParameterf") << GLLogEnum(pname) << param; -} -void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glPointParameterfv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glPointParameterfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} -void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) { - CALL_GL_API(glPointParameterx, pname, param); - GLLog("glPointParameterx") << GLLogEnum(pname) << GLLogFixed(param); -} -void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) { - CALL_GL_API(glPointParameterxv, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glPointParameterxv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} -void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { - CALL_GL_API(glColor4ub, red, green, blue, alpha); - GLLog("glColor4ub") << red << green << blue << alpha; -} -void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) { - CALL_GL_API(glTexEnvi, target, pname, param); - GLLog("glTexEnvi") << GLLogEnum(target) << GLLogEnum(pname) << param; -} -void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) { - CALL_GL_API(glTexEnviv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glTexEnviv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); -} - -void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) { - CALL_GL_API(glTexParameterfv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glTexParameterfv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params); -} - -void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) { - CALL_GL_API(glTexParameteriv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glTexParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params); -} - -void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) { - CALL_GL_API(glTexParameteri, target, pname, param); - GLLog("glTexParameteri") << GLLogEnum(target) << GLLogEnum(pname) << param; -} -void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) { - CALL_GL_API(glTexParameterxv, target, pname, params); - // XXX: we need to compute the size of this buffer - GLLog("glTexParameterxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); -} -void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) { - CALL_GL_API(glPointSizePointerOES, type, stride, pointer); - GLLog("glPointSizePointerOES") << GLLogEnum(type) << stride << pointer; -} - -// Extensions -void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { - CALL_GL_API(glDrawTexsOES, x, y, z, w, h); - GLLog("glDrawTexsOES") << x << y << z << w << h; -} -void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) { - CALL_GL_API(glDrawTexiOES, x, y, z, w, h); - GLLog("glDrawTexiOES") << x << y << z << w << h; -} -void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) { - CALL_GL_API(glDrawTexfOES, x, y, z, w, h); - GLLog("glDrawTexfOES") << x << y << z << w << h; -} -void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { - CALL_GL_API(glDrawTexxOES, x, y, z, w, h); - GLLog("glDrawTexfOES") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z) << GLLogFixed(w) << GLLogFixed(h); -} -void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) { - CALL_GL_API(glDrawTexsvOES, coords); - GLLog("glDrawTexsvOES") << GLLogBuffer<GLshort>(coords, 5); -} -void API_ENTRY(glDrawTexivOES)(const GLint* coords) { - CALL_GL_API(glDrawTexivOES, coords); - GLLog("glDrawTexivOES") << GLLogBuffer<GLint>(coords, 5); -} -void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) { - CALL_GL_API(glDrawTexfvOES, coords); - GLLog("glDrawTexfvOES") << GLLogBuffer<GLfloat>(coords, 5); -} -void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) { - CALL_GL_API(glDrawTexxvOES, coords); - GLLog("glDrawTexxvOES") << GLLogBuffer<GLfixed>(coords, 5); -} -GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) { - GLLog("glQueryMatrixxOES") << GLLogBuffer<GLfixed>(mantissa, 16) << GLLogBuffer<GLfixed>(exponent, 16); - CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent); -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/opengl/libs/GLES_CM/glext_api.in b/opengl/libs/GLES_CM/glext_api.in new file mode 100644 index 0000000..2c8648e --- /dev/null +++ b/opengl/libs/GLES_CM/glext_api.in @@ -0,0 +1,270 @@ +void API_ENTRY(glBlendEquationSeparateOES)(GLenum modeRGB, GLenum modeAlpha) { + CALL_GL_API(glBlendEquationSeparateOES, modeRGB, modeAlpha); +} +void API_ENTRY(glBlendFuncSeparateOES)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { + CALL_GL_API(glBlendFuncSeparateOES, srcRGB, dstRGB, srcAlpha, dstAlpha); +} +void API_ENTRY(glBlendEquationOES)(GLenum mode) { + CALL_GL_API(glBlendEquationOES, mode); +} +void API_ENTRY(glDrawTexsOES)(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) { + CALL_GL_API(glDrawTexsOES, x, y, z, width, height); +} +void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint width, GLint height) { + CALL_GL_API(glDrawTexiOES, x, y, z, width, height); +} +void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) { + CALL_GL_API(glDrawTexxOES, x, y, z, width, height); +} +void API_ENTRY(glDrawTexsvOES)(const GLshort *coords) { + CALL_GL_API(glDrawTexsvOES, coords); +} +void API_ENTRY(glDrawTexivOES)(const GLint *coords) { + CALL_GL_API(glDrawTexivOES, coords); +} +void API_ENTRY(glDrawTexxvOES)(const GLfixed *coords) { + CALL_GL_API(glDrawTexxvOES, coords); +} +void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) { + CALL_GL_API(glDrawTexfOES, x, y, z, width, height); +} +void API_ENTRY(glDrawTexfvOES)(const GLfloat *coords) { + CALL_GL_API(glDrawTexfvOES, coords); +} +void API_ENTRY(__glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) { + CALL_GL_API(glEGLImageTargetTexture2DOES, target, image); +} +void API_ENTRY(__glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image) { + CALL_GL_API(glEGLImageTargetRenderbufferStorageOES, target, image); +} +void API_ENTRY(glAlphaFuncxOES)(GLenum func, GLclampx ref) { + CALL_GL_API(glAlphaFuncxOES, func, ref); +} +void API_ENTRY(glClearColorxOES)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { + CALL_GL_API(glClearColorxOES, red, green, blue, alpha); +} +void API_ENTRY(glClearDepthxOES)(GLclampx depth) { + CALL_GL_API(glClearDepthxOES, depth); +} +void API_ENTRY(glClipPlanexOES)(GLenum plane, const GLfixed *equation) { + CALL_GL_API(glClipPlanexOES, plane, equation); +} +void API_ENTRY(glColor4xOES)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) { + CALL_GL_API(glColor4xOES, red, green, blue, alpha); +} +void API_ENTRY(glDepthRangexOES)(GLclampx zNear, GLclampx zFar) { + CALL_GL_API(glDepthRangexOES, zNear, zFar); +} +void API_ENTRY(glFogxOES)(GLenum pname, GLfixed param) { + CALL_GL_API(glFogxOES, pname, param); +} +void API_ENTRY(glFogxvOES)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glFogxvOES, pname, params); +} +void API_ENTRY(glFrustumxOES)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) { + CALL_GL_API(glFrustumxOES, left, right, bottom, top, zNear, zFar); +} +void API_ENTRY(glGetClipPlanexOES)(GLenum pname, GLfixed eqn[4]) { + CALL_GL_API(glGetClipPlanexOES, pname, eqn); +} +void API_ENTRY(glGetFixedvOES)(GLenum pname, GLfixed *params) { + CALL_GL_API(glGetFixedvOES, pname, params); +} +void API_ENTRY(glGetLightxvOES)(GLenum light, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetLightxvOES, light, pname, params); +} +void API_ENTRY(glGetMaterialxvOES)(GLenum face, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetMaterialxvOES, face, pname, params); +} +void API_ENTRY(glGetTexEnvxvOES)(GLenum env, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexEnvxvOES, env, pname, params); +} +void API_ENTRY(glGetTexParameterxvOES)(GLenum target, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexParameterxvOES, target, pname, params); +} +void API_ENTRY(glLightModelxOES)(GLenum pname, GLfixed param) { + CALL_GL_API(glLightModelxOES, pname, param); +} +void API_ENTRY(glLightModelxvOES)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glLightModelxvOES, pname, params); +} +void API_ENTRY(glLightxOES)(GLenum light, GLenum pname, GLfixed param) { + CALL_GL_API(glLightxOES, light, pname, param); +} +void API_ENTRY(glLightxvOES)(GLenum light, GLenum pname, const GLfixed *params) { + CALL_GL_API(glLightxvOES, light, pname, params); +} +void API_ENTRY(glLineWidthxOES)(GLfixed width) { + CALL_GL_API(glLineWidthxOES, width); +} +void API_ENTRY(glLoadMatrixxOES)(const GLfixed *m) { + CALL_GL_API(glLoadMatrixxOES, m); +} +void API_ENTRY(glMaterialxOES)(GLenum face, GLenum pname, GLfixed param) { + CALL_GL_API(glMaterialxOES, face, pname, param); +} +void API_ENTRY(glMaterialxvOES)(GLenum face, GLenum pname, const GLfixed *params) { + CALL_GL_API(glMaterialxvOES, face, pname, params); +} +void API_ENTRY(glMultMatrixxOES)(const GLfixed *m) { + CALL_GL_API(glMultMatrixxOES, m); +} +void API_ENTRY(glMultiTexCoord4xOES)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) { + CALL_GL_API(glMultiTexCoord4xOES, target, s, t, r, q); +} +void API_ENTRY(glNormal3xOES)(GLfixed nx, GLfixed ny, GLfixed nz) { + CALL_GL_API(glNormal3xOES, nx, ny, nz); +} +void API_ENTRY(glOrthoxOES)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) { + CALL_GL_API(glOrthoxOES, left, right, bottom, top, zNear, zFar); +} +void API_ENTRY(glPointParameterxOES)(GLenum pname, GLfixed param) { + CALL_GL_API(glPointParameterxOES, pname, param); +} +void API_ENTRY(glPointParameterxvOES)(GLenum pname, const GLfixed *params) { + CALL_GL_API(glPointParameterxvOES, pname, params); +} +void API_ENTRY(glPointSizexOES)(GLfixed size) { + CALL_GL_API(glPointSizexOES, size); +} +void API_ENTRY(glPolygonOffsetxOES)(GLfixed factor, GLfixed units) { + CALL_GL_API(glPolygonOffsetxOES, factor, units); +} +void API_ENTRY(glRotatexOES)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glRotatexOES, angle, x, y, z); +} +void API_ENTRY(glSampleCoveragexOES)(GLclampx value, GLboolean invert) { + CALL_GL_API(glSampleCoveragexOES, value, invert); +} +void API_ENTRY(glScalexOES)(GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glScalexOES, x, y, z); +} +void API_ENTRY(glTexEnvxOES)(GLenum target, GLenum pname, GLfixed param) { + CALL_GL_API(glTexEnvxOES, target, pname, param); +} +void API_ENTRY(glTexEnvxvOES)(GLenum target, GLenum pname, const GLfixed *params) { + CALL_GL_API(glTexEnvxvOES, target, pname, params); +} +void API_ENTRY(glTexParameterxOES)(GLenum target, GLenum pname, GLfixed param) { + CALL_GL_API(glTexParameterxOES, target, pname, param); +} +void API_ENTRY(glTexParameterxvOES)(GLenum target, GLenum pname, const GLfixed *params) { + CALL_GL_API(glTexParameterxvOES, target, pname, params); +} +void API_ENTRY(glTranslatexOES)(GLfixed x, GLfixed y, GLfixed z) { + CALL_GL_API(glTranslatexOES, x, y, z); +} +GLboolean API_ENTRY(glIsRenderbufferOES)(GLuint renderbuffer) { + CALL_GL_API_RETURN(glIsRenderbufferOES, renderbuffer); +} +void API_ENTRY(glBindRenderbufferOES)(GLenum target, GLuint renderbuffer) { + CALL_GL_API(glBindRenderbufferOES, target, renderbuffer); +} +void API_ENTRY(glDeleteRenderbuffersOES)(GLsizei n, const GLuint* renderbuffers) { + CALL_GL_API(glDeleteRenderbuffersOES, n, renderbuffers); +} +void API_ENTRY(glGenRenderbuffersOES)(GLsizei n, GLuint* renderbuffers) { + CALL_GL_API(glGenRenderbuffersOES, n, renderbuffers); +} +void API_ENTRY(glRenderbufferStorageOES)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { + CALL_GL_API(glRenderbufferStorageOES, target, internalformat, width, height); +} +void API_ENTRY(glGetRenderbufferParameterivOES)(GLenum target, GLenum pname, GLint* params) { + CALL_GL_API(glGetRenderbufferParameterivOES, target, pname, params); +} +GLboolean API_ENTRY(glIsFramebufferOES)(GLuint framebuffer) { + CALL_GL_API_RETURN(glIsFramebufferOES, framebuffer); +} +void API_ENTRY(glBindFramebufferOES)(GLenum target, GLuint framebuffer) { + CALL_GL_API(glBindFramebufferOES, target, framebuffer); +} +void API_ENTRY(glDeleteFramebuffersOES)(GLsizei n, const GLuint* framebuffers) { + CALL_GL_API(glDeleteFramebuffersOES, n, framebuffers); +} +void API_ENTRY(glGenFramebuffersOES)(GLsizei n, GLuint* framebuffers) { + CALL_GL_API(glGenFramebuffersOES, n, framebuffers); +} +GLenum API_ENTRY(glCheckFramebufferStatusOES)(GLenum target) { + CALL_GL_API_RETURN(glCheckFramebufferStatusOES, target); +} +void API_ENTRY(glFramebufferRenderbufferOES)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { + CALL_GL_API(glFramebufferRenderbufferOES, target, attachment, renderbuffertarget, renderbuffer); +} +void API_ENTRY(glFramebufferTexture2DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { + CALL_GL_API(glFramebufferTexture2DOES, target, attachment, textarget, texture, level); +} +void API_ENTRY(glGetFramebufferAttachmentParameterivOES)(GLenum target, GLenum attachment, GLenum pname, GLint* params) { + CALL_GL_API(glGetFramebufferAttachmentParameterivOES, target, attachment, pname, params); +} +void API_ENTRY(glGenerateMipmapOES)(GLenum target) { + CALL_GL_API(glGenerateMipmapOES, target); +} +void* API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) { + CALL_GL_API_RETURN(glMapBufferOES, target, access); +} +GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) { + CALL_GL_API_RETURN(glUnmapBufferOES, target); +} +void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void** params) { + CALL_GL_API(glGetBufferPointervOES, target, pname, params); +} +void API_ENTRY(glCurrentPaletteMatrixOES)(GLuint matrixpaletteindex) { + CALL_GL_API(glCurrentPaletteMatrixOES, matrixpaletteindex); +} +void API_ENTRY(glLoadPaletteFromModelViewMatrixOES)(void) { + CALL_GL_API(glLoadPaletteFromModelViewMatrixOES); +} +void API_ENTRY(glMatrixIndexPointerOES)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glMatrixIndexPointerOES, size, type, stride, pointer); +} +void API_ENTRY(glWeightPointerOES)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { + CALL_GL_API(glWeightPointerOES, size, type, stride, pointer); +} +GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed mantissa[16], GLint exponent[16]) { + CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent); +} +void API_ENTRY(glDepthRangefOES)(GLclampf zNear, GLclampf zFar) { + CALL_GL_API(glDepthRangefOES, zNear, zFar); +} +void API_ENTRY(glFrustumfOES)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) { + CALL_GL_API(glFrustumfOES, left, right, bottom, top, zNear, zFar); +} +void API_ENTRY(glOrthofOES)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) { + CALL_GL_API(glOrthofOES, left, right, bottom, top, zNear, zFar); +} +void API_ENTRY(glClipPlanefOES)(GLenum plane, const GLfloat *equation) { + CALL_GL_API(glClipPlanefOES, plane, equation); +} +void API_ENTRY(glGetClipPlanefOES)(GLenum pname, GLfloat eqn[4]) { + CALL_GL_API(glGetClipPlanefOES, pname, eqn); +} +void API_ENTRY(glClearDepthfOES)(GLclampf depth) { + CALL_GL_API(glClearDepthfOES, depth); +} +void API_ENTRY(glTexGenfOES)(GLenum coord, GLenum pname, GLfloat param) { + CALL_GL_API(glTexGenfOES, coord, pname, param); +} +void API_ENTRY(glTexGenfvOES)(GLenum coord, GLenum pname, const GLfloat *params) { + CALL_GL_API(glTexGenfvOES, coord, pname, params); +} +void API_ENTRY(glTexGeniOES)(GLenum coord, GLenum pname, GLint param) { + CALL_GL_API(glTexGeniOES, coord, pname, param); +} +void API_ENTRY(glTexGenivOES)(GLenum coord, GLenum pname, const GLint *params) { + CALL_GL_API(glTexGenivOES, coord, pname, params); +} +void API_ENTRY(glTexGenxOES)(GLenum coord, GLenum pname, GLfixed param) { + CALL_GL_API(glTexGenxOES, coord, pname, param); +} +void API_ENTRY(glTexGenxvOES)(GLenum coord, GLenum pname, const GLfixed *params) { + CALL_GL_API(glTexGenxvOES, coord, pname, params); +} +void API_ENTRY(glGetTexGenfvOES)(GLenum coord, GLenum pname, GLfloat *params) { + CALL_GL_API(glGetTexGenfvOES, coord, pname, params); +} +void API_ENTRY(glGetTexGenivOES)(GLenum coord, GLenum pname, GLint *params) { + CALL_GL_API(glGetTexGenivOES, coord, pname, params); +} +void API_ENTRY(glGetTexGenxvOES)(GLenum coord, GLenum pname, GLfixed *params) { + CALL_GL_API(glGetTexGenxvOES, coord, pname, params); +} diff --git a/opengl/libs/egl_entries.in b/opengl/libs/egl_entries.in index 33b4c65..3b4551b 100644 --- a/opengl/libs/egl_entries.in +++ b/opengl/libs/egl_entries.in @@ -43,3 +43,10 @@ EGL_ENTRY(EGLSurface, eglCreatePbufferFromClientBuffer, EGLDisplay, EGLenum, EGL /* EGL 1.3 */ /* EGL 1.4 */ + +/* EGL_EGLEXT_VERSION 3 */ + +EGL_ENTRY(EGLBoolean, eglLockSurfaceKHR, EGLDisplay, EGLSurface, const EGLint *) +EGL_ENTRY(EGLBoolean, eglUnlockSurfaceKHR, EGLDisplay, EGLSurface) +EGL_ENTRY(EGLImageKHR, eglCreateImageKHR, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *) +EGL_ENTRY(EGLBoolean, eglDestroyImageKHR, EGLDisplay, EGLImageKHR) diff --git a/opengl/libs/gl_entries.in b/opengl/libs/gl_entries.in index b97e8fe..d7cc5da 100644 --- a/opengl/libs/gl_entries.in +++ b/opengl/libs/gl_entries.in @@ -1,159 +1,145 @@ -GL_ENTRY(void, glColor4f, GLfloat, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glColor4x, GLfixed, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glNormal3f, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glNormal3x, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glCullFace, GLenum) -GL_ENTRY(void, glFrontFace, GLenum) -GL_ENTRY(void, glDisable, GLenum) -GL_ENTRY(void, glEnable, GLenum) -GL_ENTRY(void, glFinish, void) -GL_ENTRY(void, glFlush, void) -GL_ENTRY(GLenum, glGetError, void) -GL_ENTRY(const GLubyte*, glGetString, GLenum) -GL_ENTRY(void, glGetIntegerv, GLenum, GLint *) -GL_ENTRY(void, glColorMask, GLboolean, GLboolean, GLboolean, GLboolean) -GL_ENTRY(void, glDepthMask, GLboolean) -GL_ENTRY(void, glStencilMask, GLuint) -GL_ENTRY(void, glDepthFunc, GLenum) +GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref) +GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +GL_ENTRY(void, glClearDepthf, GLclampf depth) +GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation) +GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar) -GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar) +GL_ENTRY(void, glFogf, GLenum pname, GLfloat param) +GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4]) +GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params) +GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param) +GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param) +GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glLineWidth, GLfloat width) +GL_ENTRY(void, glLoadMatrixf, const GLfloat *m) +GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param) +GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glMultMatrixf, const GLfloat *m) +GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz) +GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param) +GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glPointSize, GLfloat size) GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units) -GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units) -GL_ENTRY(void, glLogicOp, GLenum opcode) +GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z) +GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param) +GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param) +GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z) +GL_ENTRY(void, glActiveTexture, GLenum texture) GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref) -GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref) +GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer) +GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture) GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor) +GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) +GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) GL_ENTRY(void, glClear, GLbitfield mask) -GL_ENTRY(void, glClearColor, GLclampf r, GLclampf g, GLclampf b, GLclampf a) -GL_ENTRY(void, glClearColorx, GLclampx r, GLclampx g, GLclampx b, GLclampx a) -GL_ENTRY(void, glClearDepthf, GLclampf depth) +GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) GL_ENTRY(void, glClearDepthx, GLclampx depth) GL_ENTRY(void, glClearStencil, GLint s) -GL_ENTRY(void, glPointSize, GLfloat) -GL_ENTRY(void, glPointSizex, GLfixed) -GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert) -GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert) -GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask) -GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass) -GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height) -GL_ENTRY(void, glHint, GLenum, GLenum mode) -GL_ENTRY(void, glLineWidth, GLfloat width) +GL_ENTRY(void, glClientActiveTexture, GLenum texture) +GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation) +GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) +GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) +GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glCullFace, GLenum mode) +GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers) +GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures) +GL_ENTRY(void, glDepthFunc, GLenum func) +GL_ENTRY(void, glDepthMask, GLboolean flag) +GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar) +GL_ENTRY(void, glDisable, GLenum cap) +GL_ENTRY(void, glDisableClientState, GLenum array) +GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count) +GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) +GL_ENTRY(void, glEnable, GLenum cap) +GL_ENTRY(void, glEnableClientState, GLenum array) +GL_ENTRY(void, glFinish, void) +GL_ENTRY(void, glFlush, void) +GL_ENTRY(void, glFogx, GLenum pname, GLfixed param) +GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glFrontFace, GLenum mode) +GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params) +GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params) +GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4]) +GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers) +GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures) +GL_ENTRY(GLenum, glGetError, void) +GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params) +GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetPointerv, GLenum pname, void **params) +GL_ENTRY(const GLubyte *, glGetString, GLenum name) +GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params) +GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params) +GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params) +GL_ENTRY(void, glHint, GLenum target, GLenum mode) +GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer) +GL_ENTRY(GLboolean, glIsEnabled, GLenum cap) +GL_ENTRY(GLboolean, glIsTexture, GLuint texture) +GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param) +GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param) +GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params) GL_ENTRY(void, glLineWidthx, GLfixed width) -GL_ENTRY(void, glShadeModel, GLenum) -GL_ENTRY(void, glLightModelf, GLenum, GLfloat) -GL_ENTRY(void, glLightModelfv, GLenum, const GLfloat *) -GL_ENTRY(void, glLightModelx, GLenum, GLfixed) -GL_ENTRY(void, glLightModelxv, GLenum, const GLfixed *) -GL_ENTRY(void, glLightf, GLenum, GLenum, GLfloat) -GL_ENTRY(void, glLightfv, GLenum, GLenum, const GLfloat *) -GL_ENTRY(void, glLightx, GLenum, GLenum, GLfixed) -GL_ENTRY(void, glLightxv, GLenum, GLenum, const GLfixed *) -GL_ENTRY(void, glMaterialf, GLenum, GLenum, GLfloat) -GL_ENTRY(void, glMaterialfv, GLenum, GLenum, const GLfloat *) -GL_ENTRY(void, glMaterialx, GLenum, GLenum, GLfixed) -GL_ENTRY(void, glMaterialxv, GLenum, GLenum, const GLfixed *) -GL_ENTRY(void, glFogf, GLenum, GLfloat) -GL_ENTRY(void, glFogfv, GLenum, const GLfloat *) -GL_ENTRY(void, glFogx, GLenum, GLfixed) -GL_ENTRY(void, glFogxv, GLenum, const GLfixed *) -GL_ENTRY(void, glVertexPointer, GLint, GLenum, GLsizei, const GLvoid *) -GL_ENTRY(void, glColorPointer, GLint, GLenum, GLsizei, const GLvoid *) -GL_ENTRY(void, glNormalPointer, GLenum, GLsizei, const GLvoid *) -GL_ENTRY(void, glTexCoordPointer, GLint, GLenum, GLsizei, const GLvoid *) -GL_ENTRY(void, glEnableClientState, GLenum) -GL_ENTRY(void, glDisableClientState, GLenum) -GL_ENTRY(void, glClientActiveTexture, GLenum) -GL_ENTRY(void, glDrawArrays, GLenum, GLint first, GLsizei) -GL_ENTRY(void, glDrawElements, GLenum, GLsizei, GLenum, const GLvoid *) GL_ENTRY(void, glLoadIdentity, void) -GL_ENTRY(void, glLoadMatrixf, const GLfloat*) -GL_ENTRY(void, glLoadMatrixx, const GLfixed*) +GL_ENTRY(void, glLoadMatrixx, const GLfixed *m) +GL_ENTRY(void, glLogicOp, GLenum opcode) +GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param) +GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params) GL_ENTRY(void, glMatrixMode, GLenum mode) -GL_ENTRY(void, glMultMatrixf, const GLfloat*) -GL_ENTRY(void, glMultMatrixx, const GLfixed*) +GL_ENTRY(void, glMultMatrixx, const GLfixed *m) +GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz) +GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer) +GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param) +GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param) +GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glPointSizex, GLfixed size) +GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units) GL_ENTRY(void, glPopMatrix, void) GL_ENTRY(void, glPushMatrix, void) -GL_ENTRY(void, glFrustumf, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glFrustumx, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glOrthof, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glOrthox, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glRotatef, GLfloat, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glRotatex, GLfixed, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glScalef, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glScalex, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glTranslatef, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glTranslatex, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glViewport, GLint, GLint, GLsizei, GLsizei) -GL_ENTRY(void, glActiveTexture, GLenum) -GL_ENTRY(void, glBindTexture, GLenum, GLuint) -GL_ENTRY(void, glGenTextures, GLsizei, GLuint*) -GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *) -GL_ENTRY(void, glMultiTexCoord4f, GLenum, GLfloat, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glMultiTexCoord4x, GLenum, GLfixed, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glPixelStorei, GLenum, GLint) -GL_ENTRY(void, glTexEnvf, GLenum, GLenum, GLfloat) -GL_ENTRY(void, glTexEnvfv, GLenum, GLenum, const GLfloat*) -GL_ENTRY(void, glTexEnvx, GLenum, GLenum, GLfixed) -GL_ENTRY(void, glTexEnvxv, GLenum, GLenum, const GLfixed*) -GL_ENTRY(void, glTexParameterf, GLenum, GLenum, GLfloat) -GL_ENTRY(void, glTexParameterx, GLenum, GLenum, GLfixed) -GL_ENTRY(void, glCompressedTexImage2D, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*) -GL_ENTRY(void, glCompressedTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*) -GL_ENTRY(void, glCopyTexImage2D, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint) -GL_ENTRY(void, glCopyTexSubImage2D, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei) -GL_ENTRY(void, glTexImage2D, GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*) -GL_ENTRY(void, glTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*) -GL_ENTRY(void, glReadPixels, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *) - -// 1.1 additions -GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat*) -GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed*) -GL_ENTRY(void, glBindBuffer, GLenum, GLuint) -GL_ENTRY(void, glBufferData, GLenum, GLsizeiptr, const GLvoid*, GLenum) -GL_ENTRY(void, glBufferSubData, GLenum, GLintptr, GLsizeiptr, const GLvoid*) -GL_ENTRY(void, glDeleteBuffers, GLsizei, const GLuint*) -GL_ENTRY(void, glGenBuffers, GLsizei, GLuint*) -GL_ENTRY(void, glGetBooleanv, GLenum, GLboolean *) -GL_ENTRY(void, glGetFixedv, GLenum, GLfixed *) -GL_ENTRY(void, glGetFloatv, GLenum, GLfloat *) -GL_ENTRY(void, glGetPointerv, GLenum, void **) -GL_ENTRY(void, glGetBufferParameteriv, GLenum, GLenum, GLint *) -GL_ENTRY(void, glGetClipPlanef, GLenum, GLfloat[4]) -GL_ENTRY(void, glGetClipPlanex, GLenum, GLfixed[4]) -GL_ENTRY(void, glGetLightxv, GLenum, GLenum, GLfixed *) -GL_ENTRY(void, glGetLightfv, GLenum, GLenum, GLfloat *) -GL_ENTRY(void, glGetMaterialxv, GLenum, GLenum, GLfixed *) -GL_ENTRY(void, glGetMaterialfv, GLenum, GLenum, GLfloat *) -GL_ENTRY(void, glGetTexEnvfv, GLenum, GLenum, GLfloat *) -GL_ENTRY(void, glGetTexEnviv, GLenum, GLenum, GLint *) -GL_ENTRY(void, glGetTexEnvxv, GLenum, GLenum, GLfixed *) -GL_ENTRY(void, glGetTexParameterfv, GLenum, GLenum, GLfloat *) -GL_ENTRY(void, glGetTexParameteriv, GLenum, GLenum, GLint *) -GL_ENTRY(void, glGetTexParameterxv, GLenum, GLenum, GLfixed *) -GL_ENTRY(GLboolean, glIsBuffer, GLuint) -GL_ENTRY(GLboolean, glIsEnabled, GLenum) -GL_ENTRY(GLboolean, glIsTexture, GLuint) -GL_ENTRY(void, glPointParameterf, GLenum, GLfloat) -GL_ENTRY(void, glPointParameterfv, GLenum, const GLfloat *) -GL_ENTRY(void, glPointParameterx, GLenum, GLfixed) -GL_ENTRY(void, glPointParameterxv, GLenum, const GLfixed *) -GL_ENTRY(void, glColor4ub, GLubyte, GLubyte, GLubyte, GLubyte) -GL_ENTRY(void, glTexEnvi, GLenum, GLenum, GLint) -GL_ENTRY(void, glTexEnviv, GLenum, GLenum, const GLint *) -GL_ENTRY(void, glTexParameterfv, GLenum, GLenum, const GLfloat *) -GL_ENTRY(void, glTexParameteriv, GLenum, GLenum, const GLint *) -GL_ENTRY(void, glTexParameteri, GLenum, GLenum, GLint) -GL_ENTRY(void, glTexParameterxv, GLenum, GLenum, const GLfixed *) -GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid*) - -// Extensions -GL_ENTRY(void, glDrawTexsOES, GLshort, GLshort, GLshort, GLshort, GLshort) -GL_ENTRY(void, glDrawTexiOES, GLint, GLint, GLint, GLint, GLint) -GL_ENTRY(void, glDrawTexfOES, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat) -GL_ENTRY(void, glDrawTexxOES, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed) -GL_ENTRY(void, glDrawTexsvOES, const GLshort*) -GL_ENTRY(void, glDrawTexivOES, const GLint*) -GL_ENTRY(void, glDrawTexfvOES, const GLfloat*) -GL_ENTRY(void, glDrawTexxvOES, const GLfixed*) -GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed* mantissa, GLint* exponent) - +GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) +GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert) +GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert) +GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glShadeModel, GLenum mode) +GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask) +GL_ENTRY(void, glStencilMask, GLuint mask) +GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass) +GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param) +GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params) +GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param) +GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params) +GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) +GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer) diff --git a/opengl/libs/gl_logger.h b/opengl/libs/gl_logger.h deleted file mode 100644 index ce85dd1..0000000 --- a/opengl/libs/gl_logger.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - ** Copyright 2007, 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. - */ - -#ifndef ANDROID_GL_LOGGER_H -#define ANDROID_GL_LOGGER_H - -namespace android { -#define GL_ENTRY(r, api, ...) r log_##api(__VA_ARGS__); -#include "gl_entries.in" -#undef GL_ENTRY -}; // namespace android - -#endif /* ANDROID_GL_LOGGER_H */ diff --git a/opengl/libs/glext_entries.in b/opengl/libs/glext_entries.in new file mode 100644 index 0000000..dd09c71 --- /dev/null +++ b/opengl/libs/glext_entries.in @@ -0,0 +1,90 @@ +GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha) +GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +GL_ENTRY(void, glBlendEquationOES, GLenum mode) +GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) +GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height) +GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) +GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords) +GL_ENTRY(void, glDrawTexivOES, const GLint *coords) +GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords) +GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) +GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords) +GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image) +GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image) +GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref) +GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) +GL_ENTRY(void, glClearDepthxOES, GLclampx depth) +GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation) +GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar) +GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param) +GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4]) +GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params) +GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param) +GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param) +GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glLineWidthxOES, GLfixed width) +GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m) +GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param) +GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m) +GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz) +GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param) +GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glPointSizexOES, GLfixed size) +GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units) +GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert) +GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer) +GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer) +GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers) +GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers) +GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params) +GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer) +GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer) +GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers) +GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers) +GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target) +GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params) +GL_ENTRY(void, glGenerateMipmapOES, GLenum target) +GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access) +GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target) +GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params) +GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex) +GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void) +GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16]) +GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar) +GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation) +GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4]) +GL_ENTRY(void, glClearDepthfOES, GLclampf depth) +GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param) +GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param) +GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params) +GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params) +GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params) diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h index 63fb017..fd97254 100644 --- a/opengl/libs/hooks.h +++ b/opengl/libs/hooks.h @@ -22,9 +22,10 @@ #include <errno.h> #include <EGL/egl.h> +#include <EGL/eglext.h> #include <GLES/gl.h> +#include <GLES/glext.h> -#define GL_LOGGER 0 #if !defined(__arm__) #define USE_SLOW_BINDING 1 #else @@ -35,7 +36,7 @@ #define MAX_NUMBER_OF_GL_EXTENSIONS 32 -#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && !GL_LOGGER && __OPTIMIZE__ +#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && __OPTIMIZE__ #define USE_FAST_TLS_KEY 1 #else #define USE_FAST_TLS_KEY 0 @@ -55,7 +56,10 @@ const unsigned int NUM_DISPLAYS = 1; enum { IMPL_HARDWARE = 0, IMPL_SOFTWARE, - IMPL_CONTEXT_LOST, + + IMPL_NUM_DRIVERS_IMPLEMENTATIONS, + + IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS, IMPL_NO_CONTEXT, IMPL_NUM_IMPLEMENTATIONS @@ -73,6 +77,7 @@ enum { struct gl_hooks_t { struct gl_t { #include "gl_entries.in" + #include "glext_entries.in" } gl; struct egl_t { #include "egl_entries.in" diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles new file mode 100755 index 0000000..107768b --- /dev/null +++ b/opengl/libs/tools/genfiles @@ -0,0 +1,20 @@ +#! /bin/sh +# +# Copyright (C) 2008 Google Inc. +# +# 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. + +./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in +./glentrygen ../../include/GLES/gl.h > ../gl_entries.in +./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in +./glentrygen ../../include/GLES/glext.h > ../glext_entries.in diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen new file mode 100755 index 0000000..a2c3a7b --- /dev/null +++ b/opengl/libs/tools/glapigen @@ -0,0 +1,72 @@ +#! /usr/bin/perl +# +# Copyright (C) 2008 Google Inc. +# +# 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. + +use strict; + +while (my $line = <>) { + next if $line =~ /^\//; + next if $line =~ /^#/; + next if $line =~ /^\s*$/; + if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { + next; + } + my $type = $1; + my $name = $2; + my $args = $3; + + #printf("%s", $line); + + my $prefix = ""; + if ($name eq "glEGLImageTargetTexture2DOES") { + $prefix = "__"; + } + if ($name eq "glEGLImageTargetRenderbufferStorageOES") { + $prefix = "__"; + } + + printf("%s API_ENTRY(%s%s)(%s)", $type, $prefix, $name, $args); + + printf(" {\n"); + if ($type eq "void") { + printf(" CALL_GL_API(%s", $name); + } else { + printf(" CALL_GL_API_RETURN(%s", $name); + } + my @args = split ',', $args; + my $len = scalar(@args); + for (my $num = 0; $num < $len; $num++) { + if ($args[$num] ne "void") { + print ", "; + # + # extract the name from the parameter + # type name + # const type *name + # type *name + # type name[4] + # + if ($args[$num] =~ /(\S+\s)+\**\s*([\w]+)/) { + printf("%s", $2); + } + } + } + printf(");\n"); + printf("}\n"); +} + + + + + diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen new file mode 100755 index 0000000..5e0f7b6 --- /dev/null +++ b/opengl/libs/tools/glentrygen @@ -0,0 +1,31 @@ +#! /usr/bin/perl +# +# Copyright (C) 2008 Google Inc. +# +# 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. + +use strict; + +while (my $line = <>) { + next if $line =~ /^\//; + next if $line =~ /^#/; + next if $line =~ /^\s*$/; + if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { + next; + } + my $type = $1; + my $name = $2; + my $args = $3; + + printf("GL_ENTRY(%s, %s, %s)\n", $type, $name, $args); +} diff --git a/opengl/tools/glgen/specs/gles11/checks.spec b/opengl/tools/glgen/specs/gles11/checks.spec index 9ff1205..97dac2e 100644 --- a/opengl/tools/glgen/specs/gles11/checks.spec +++ b/opengl/tools/glgen/specs/gles11/checks.spec @@ -59,87 +59,3 @@ glTexGenf unsupported glTexGeni unsupported
glTexGenx unsupported
glWeightPointerOES unsupported
-// Lots of unsupported
-glAlphaFuncxOES unsupported
-glBlendEquationOES unsupported
-glBlendEquationSeparateOES unsupported
-glBlendFuncSeparateOES unsupported
-glClearColorxOES unsupported
-glClearDepthfOES unsupported
-glClearDepthxOES unsupported
-glClipPlanefOES unsupported
-glClipPlanefOES unsupported
-glClipPlanexOES unsupported
-glClipPlanexOES unsupported
-glColor4xOES unsupported
-glDepthRangefOES unsupported
-glDepthRangexOES unsupported
-glEGLImageTargetRenderbufferStorageOES unsupported
-glEGLImageTargetTexture2DOES unsupported
-glFogxOES unsupported
-glFogxvOES unsupported
-glFogxvOES unsupported
-glFrustumfOES unsupported
-glFrustumxOES unsupported
-glGetClipPlanefOES unsupported
-glGetClipPlanefOES unsupported
-glGetClipPlanexOES unsupported
-glGetClipPlanexOES unsupported
-glGetFixedvOES unsupported
-glGetFixedvOES unsupported
-glGetLightxvOES unsupported
-glGetLightxvOES unsupported
-glGetMaterialxvOES unsupported
-glGetMaterialxvOES unsupported
-glGetTexEnvxvOES unsupported
-glGetTexEnvxvOES unsupported
-glGetTexGenfvOES unsupported
-glGetTexGenfvOES unsupported
-glGetTexGenivOES unsupported
-glGetTexGenivOES unsupported
-glGetTexGenxvOES unsupported
-glGetTexGenxvOES unsupported
-glGetTexParameterxvOES unsupported
-glGetTexParameterxvOES unsupported
-glLightModelxOES unsupported
-glLightModelxvOES unsupported
-glLightModelxvOES unsupported
-glLightxOES unsupported
-glLightxvOES unsupported
-glLightxvOES unsupported
-glLineWidthxOES unsupported
-glLoadMatrixxOES unsupported
-glLoadMatrixxOES unsupported
-glMaterialxOES unsupported
-glMaterialxvOES unsupported
-glMaterialxvOES unsupported
-glMultMatrixxOES unsupported
-glMultMatrixxOES unsupported
-glMultiTexCoord4xOES unsupported
-glNormal3xOES unsupported
-glOrthofOES unsupported
-glOrthoxOES unsupported
-glPointParameterxOES unsupported
-glPointParameterxvOES unsupported
-glPointParameterxvOES unsupported
-glPointSizexOES unsupported
-glPolygonOffsetxOES unsupported
-glRotatexOES unsupported
-glSampleCoveragexOES unsupported
-glScalexOES unsupported
-glTexEnvxOES unsupported
-glTexEnvxvOES unsupported
-glTexEnvxvOES unsupported
-glTexGenfOES unsupported
-glTexGenfvOES unsupported
-glTexGenfvOES unsupported
-glTexGeniOES unsupported
-glTexGenivOES unsupported
-glTexGenivOES unsupported
-glTexGenxOES unsupported
-glTexGenxvOES unsupported
-glTexGenxvOES unsupported
-glTexParameterxOES unsupported
-glTexParameterxvOES unsupported
-glTexParameterxvOES unsupported
-glTranslatexOES unsupported
\ No newline at end of file diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.java b/opengl/tools/glgen/stubs/gles11/glGetString.java index 8c7881c..fba249b 100644 --- a/opengl/tools/glgen/stubs/gles11/glGetString.java +++ b/opengl/tools/glgen/stubs/gles11/glGetString.java @@ -1,16 +1,5 @@ // C function const GLubyte * glGetString ( GLenum name )
- public native String _glGetString(
+ public static native String glGetString(
int name
);
-
- public String glGetString(
- int name
- ) {
- String returnValue;
- returnValue = _glGetString(
- name
- );
- return returnValue;
- }
-
diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg index e64187c..a4af31f 100644 --- a/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg +++ b/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg @@ -1 +1 @@ -{"_glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString },
+{"glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString },
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index d66c6e5..9c4ace1 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -413,41 +413,45 @@ class AlarmManagerService extends IAlarmManager.Stub { synchronized (mLock) { pw.println("Current Alarm Manager state:"); - if (mRtcWakeupAlarms.size() > 0) { + if (mRtcWakeupAlarms.size() > 0 || mRtcAlarms.size() > 0) { pw.println(" "); - pw.println(" Realtime wakeup alarms that are scheduled:"); - dumpAlarmList(pw, mRtcWakeupAlarms, " ", "RTC_WAKEUP"); - } - if (mRtcAlarms.size() > 0) { - pw.println(" "); - pw.println(" Realtime alarms that are scheduled:"); - dumpAlarmList(pw, mRtcAlarms, " ", "RTC"); - } - if (mElapsedRealtimeWakeupAlarms.size() > 0) { - pw.println(" "); - pw.println(" Elapsed realtime wakeup alarms that are scheduled:"); - dumpAlarmList(pw, mElapsedRealtimeWakeupAlarms, " ", "ELAPSED_REALTIME_WAKEUP"); + pw.print(" Realtime wakeup (now="); + pw.print(System.currentTimeMillis()); pw.println("):"); + if (mRtcWakeupAlarms.size() > 0) { + dumpAlarmList(pw, mRtcWakeupAlarms, " ", "RTC_WAKEUP"); + } + if (mRtcAlarms.size() > 0) { + dumpAlarmList(pw, mRtcAlarms, " ", "RTC"); + } } - if (mElapsedRealtimeAlarms.size() > 0) { + if (mElapsedRealtimeWakeupAlarms.size() > 0 || mElapsedRealtimeAlarms.size() > 0) { pw.println(" "); - pw.println(" Elapsed realtime alarms that are scheduled:"); - dumpAlarmList(pw, mElapsedRealtimeAlarms, " ", "ELAPSED_REALTIME"); + pw.print(" Elapsed realtime wakeup (now="); + pw.print(SystemClock.elapsedRealtime()); pw.println("):"); + if (mElapsedRealtimeWakeupAlarms.size() > 0) { + dumpAlarmList(pw, mElapsedRealtimeWakeupAlarms, " ", "ELAPSED_WAKEUP"); + } + if (mElapsedRealtimeAlarms.size() > 0) { + dumpAlarmList(pw, mElapsedRealtimeAlarms, " ", "ELAPSED"); + } } pw.println(" "); - pw.println(" Broadcast ref count: " + mBroadcastRefCount); + pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount); pw.println(" "); pw.println(" Alarm Stats:"); for (Map.Entry<String, BroadcastStats> be : mBroadcastStats.entrySet()) { BroadcastStats bs = be.getValue(); - pw.println(" " + be.getKey()); - pw.println(" " + bs.aggregateTime + "ms running, " - + bs.numWakeup + " wakeups"); + pw.print(" "); pw.println(be.getKey()); + pw.print(" "); pw.print(bs.aggregateTime); + pw.print("ms running, "); pw.print(bs.numWakeup); + pw.println(" wakeups"); for (Map.Entry<Intent.FilterComparison, FilterStats> fe : bs.filterStats.entrySet()) { - pw.println(" " + fe.getValue().count + " alarms: " - + fe.getKey().getIntent()); + pw.print(" "); pw.print(fe.getValue().count); + pw.print(" alarms: "); + pw.println(fe.getKey().getIntent().toShortString(true, false)); } } } @@ -456,7 +460,8 @@ class AlarmManagerService extends IAlarmManager.Stub { private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, String prefix, String label) { for (int i=list.size()-1; i>=0; i--) { Alarm a = list.get(i); - pw.println(prefix + label + " #" + i + ":"); + pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i); + pw.print(": "); pw.println(a); a.dump(pw, prefix + " "); } } @@ -561,18 +566,24 @@ class AlarmManagerService extends IAlarmManager.Stub { @Override public String toString() { - return "Alarm{" - + Integer.toHexString(System.identityHashCode(this)) - + " type " + type + " " + operation.getTargetPackage() + "}"; + StringBuilder sb = new StringBuilder(128); + sb.append("Alarm{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(" type "); + sb.append(type); + sb.append(" "); + sb.append(operation.getTargetPackage()); + sb.append('}'); + return sb.toString(); } public void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "type=" + type + " when=" + when - + " repeatInterval=" + repeatInterval - + " count=" + count); - pw.println(prefix + "operation=" + operation); + pw.print(prefix); pw.print("type="); pw.print(type); + pw.print(" when="); pw.print(when); + pw.print(" repeatInterval="); pw.print(repeatInterval); + pw.print(" count="); pw.println(count); + pw.print(prefix); pw.print("operation="); pw.println(operation); } } diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index de5d0ac..bb420a6 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -151,34 +151,57 @@ class AppWidgetService extends IAppWidgetService.Stub synchronized (mAppWidgetIds) { int N = mInstalledProviders.size(); - pw.println("Providers: (size=" + N + ")"); + pw.println("Providers:"); for (int i=0; i<N; i++) { Provider p = mInstalledProviders.get(i); AppWidgetProviderInfo info = p.info; - pw.println(" [" + i + "] provder=" + info.provider - + " min=(" + info.minWidth + "x" + info.minHeight + ")" - + " updatePeriodMillis=" + info.updatePeriodMillis - + " initialLayout=" + info.initialLayout + " zombie=" + p.zombie); + pw.print(" ["); pw.print(i); pw.print("] provider "); + pw.print(info.provider.flattenToShortString()); + pw.println(':'); + pw.print(" min=("); pw.print(info.minWidth); + pw.print("x"); pw.print(info.minHeight); + pw.print(") updatePeriodMillis="); + pw.print(info.updatePeriodMillis); + pw.print(" initialLayout=#"); + pw.print(Integer.toHexString(info.initialLayout)); + pw.print(" zombie="); pw.println(p.zombie); } N = mAppWidgetIds.size(); - pw.println("AppWidgetIds: (size=" + N + ")"); + pw.println(" "); + pw.println("AppWidgetIds:"); for (int i=0; i<N; i++) { AppWidgetId id = mAppWidgetIds.get(i); - pw.println(" [" + i + "] appWidgetId=" + id.appWidgetId - + " host=" + id.host.hostId + "/" + id.host.packageName + " provider=" - + (id.provider == null ? "null" : id.provider.info.provider) - + " host.callbacks=" + (id.host != null ? id.host.callbacks : "(no host)") - + " views=" + id.views); + pw.print(" ["); pw.print(i); pw.print("] id="); + pw.println(id.appWidgetId);; + pw.print(" hostId="); + pw.print(id.host.hostId); pw.print(' '); + pw.print(id.host.packageName); pw.print('/'); + pw.println(id.host.uid); + if (id.provider != null) { + pw.print(" provider="); + pw.println(id.provider.info.provider.flattenToShortString()); + } + if (id.host != null) { + pw.print(" host.callbacks="); pw.println(id.host.callbacks); + } + if (id.views != null) { + pw.print(" views="); pw.println(id.views); + } } N = mHosts.size(); - pw.println("Hosts: (size=" + N + ")"); + pw.println(" "); + pw.println("Hosts:"); for (int i=0; i<N; i++) { Host host = mHosts.get(i); - pw.println(" [" + i + "] packageName=" + host.packageName + " uid=" + host.uid - + " hostId=" + host.hostId + " callbacks=" + host.callbacks - + " instances.size=" + host.instances.size() + " zombie=" + host.zombie); + pw.print(" ["); pw.print(i); pw.print("] hostId="); + pw.print(host.hostId); pw.print(' '); + pw.print(host.packageName); pw.print('/'); + pw.print(host.uid); pw.println(':'); + pw.print(" callbacks="); pw.println(host.callbacks); + pw.print(" instances.size="); pw.print(host.instances.size()); + pw.print(" zombie="); pw.println(host.zombie); } } } diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java index b534ef1..72efca5 100644 --- a/services/java/com/android/server/IntentResolver.java +++ b/services/java/com/android/server/IntentResolver.java @@ -16,6 +16,7 @@ package com.android.server; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -89,11 +90,11 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { } } - void dumpMap(Printer out, String prefix, Map<String, ArrayList<F>> map) { + void dumpMap(PrintWriter out, String prefix, Map<String, ArrayList<F>> map) { String eprefix = prefix + " "; String fprefix = prefix + " "; for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) { - out.println(eprefix + e.getKey() + ":"); + out.print(eprefix); out.print(e.getKey()); out.println(":"); ArrayList<F> a = e.getValue(); final int N = a.size(); for (int i=0; i<N; i++) { @@ -102,24 +103,25 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { } } - public void dump(Printer out, String prefix) { - out.println(prefix + "Full MIME Types:"); - dumpMap(out, prefix+" ", mTypeToFilter); - out.println(prefix); - out.println(prefix + "Base MIME Types:"); - dumpMap(out, prefix+" ", mBaseTypeToFilter); - out.println(prefix); - out.println(prefix + "Wild MIME Types:"); - dumpMap(out, prefix+" ", mWildTypeToFilter); - out.println(prefix); - out.println(prefix + "Schemes:"); - dumpMap(out, prefix+" ", mSchemeToFilter); - out.println(prefix); - out.println(prefix + "Non-Data Actions:"); - dumpMap(out, prefix+" ", mActionToFilter); - out.println(prefix); - out.println(prefix + "MIME Typed Actions:"); - dumpMap(out, prefix+" ", mTypedActionToFilter); + public void dump(PrintWriter out, String prefix) { + String innerPrefix = prefix + " "; + out.print(prefix); out.println("Full MIME Types:"); + dumpMap(out, innerPrefix, mTypeToFilter); + out.println(" "); + out.print(prefix); out.println("Base MIME Types:"); + dumpMap(out, innerPrefix, mBaseTypeToFilter); + out.println(" "); + out.print(prefix); out.println("Wild MIME Types:"); + dumpMap(out, innerPrefix, mWildTypeToFilter); + out.println(" "); + out.print(prefix); out.println("Schemes:"); + dumpMap(out, innerPrefix, mSchemeToFilter); + out.println(" "); + out.print(prefix); out.println("Non-Data Actions:"); + dumpMap(out, innerPrefix, mActionToFilter); + out.println(" "); + out.print(prefix); out.println("MIME Typed Actions:"); + dumpMap(out, innerPrefix, mTypedActionToFilter); } private class IteratorWrapper implements Iterator<F> { @@ -275,8 +277,8 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { Collections.sort(results, mResolvePrioritySorter); } - protected void dumpFilter(Printer out, String prefix, F filter) { - out.println(prefix + filter); + protected void dumpFilter(PrintWriter out, String prefix, F filter) { + out.print(prefix); out.println(filter); } private final int register_mime_types(F filter, String prefix) { diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 5e079d4..2def877 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -93,10 +93,6 @@ public class LocationManagerService extends ILocationManager.Stub { // Max time to hold wake lock for, in milliseconds. private static final long MAX_TIME_FOR_WAKE_LOCK = 60 * 1000L; - // Time to wait after releasing a wake lock for clients to process location update, - // in milliseconds. - private static final long TIME_AFTER_WAKE_LOCK = 2 * 1000L; - // The last time a location was written, by provider name. private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>(); @@ -130,7 +126,6 @@ public class LocationManagerService extends ILocationManager.Stub { // Handler messages private static final int MESSAGE_LOCATION_CHANGED = 1; - private static final int MESSAGE_RELEASE_WAKE_LOCK = 2; // Alarm manager and wakelock variables private final static String ALARM_INTENT = "com.android.location.ALARM_INTENT"; @@ -138,6 +133,7 @@ public class LocationManagerService extends ILocationManager.Stub { private AlarmManager mAlarmManager; private long mAlarmInterval = 0; private PowerManager.WakeLock mWakeLock = null; + private int mPendingBroadcasts; private long mWakeLockAcquireTime = 0; private boolean mWakeLockGpsReceived = true; private boolean mWakeLockNetworkReceived = true; @@ -159,7 +155,8 @@ public class LocationManagerService extends ILocationManager.Stub { new HashMap<String,ArrayList<UpdateRecord>>(); // Proximity listeners - private Receiver mProximityListener = null; + private Receiver mProximityReceiver = null; + private ILocationListener mProximityListener = null; private HashMap<PendingIntent,ProximityAlert> mProximityAlerts = new HashMap<PendingIntent,ProximityAlert>(); private HashSet<ProximityAlert> mProximitiesEntered = @@ -181,11 +178,12 @@ public class LocationManagerService extends ILocationManager.Stub { * A wrapper class holding either an ILocationListener or a PendingIntent to receive * location updates. */ - private final class Receiver implements IBinder.DeathRecipient { + private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished { final ILocationListener mListener; final PendingIntent mPendingIntent; final Object mKey; final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>(); + int mPendingBroadcasts; Receiver(ILocationListener listener) { mListener = listener; @@ -252,7 +250,16 @@ public class LocationManagerService extends ILocationManager.Stub { public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { if (mListener != null) { try { - mListener.onStatusChanged(provider, status, extras); + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mListener.onStatusChanged(provider, status, extras); + if (mListener != mProximityListener) { + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } + } } catch (RemoteException e) { return false; } @@ -261,7 +268,14 @@ public class LocationManagerService extends ILocationManager.Stub { statusChanged.putExtras(extras); statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); try { - mPendingIntent.send(mContext, 0, statusChanged, null, null); + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } } catch (PendingIntent.CanceledException e) { return false; } @@ -272,7 +286,16 @@ public class LocationManagerService extends ILocationManager.Stub { public boolean callLocationChangedLocked(Location location) { if (mListener != null) { try { - mListener.onLocationChanged(location); + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mListener.onLocationChanged(location); + if (mListener != mProximityListener) { + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } + } } catch (RemoteException e) { return false; } @@ -280,7 +303,53 @@ public class LocationManagerService extends ILocationManager.Stub { Intent locationChanged = new Intent(); locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); try { - mPendingIntent.send(mContext, 0, locationChanged, null, null); + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } + } catch (PendingIntent.CanceledException e) { + return false; + } + } + return true; + } + + public boolean callProviderEnabledLocked(String provider, boolean enabled) { + if (mListener != null) { + try { + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + if (enabled) { + mListener.onProviderEnabled(provider); + } else { + mListener.onProviderDisabled(provider); + } + if (mListener != mProximityListener) { + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } + } + } catch (RemoteException e) { + return false; + } + } else { + Intent providerIntent = new Intent(); + providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); + try { + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } } catch (PendingIntent.CanceledException e) { return false; } @@ -295,6 +364,42 @@ public class LocationManagerService extends ILocationManager.Stub { synchronized (mLock) { removeUpdatesLocked(this); } + synchronized (this) { + if (mPendingBroadcasts > 0) { + LocationManagerService.this.decrementPendingBroadcasts(); + mPendingBroadcasts = 0; + } + } + } + + public void onSendFinished(PendingIntent pendingIntent, Intent intent, + int resultCode, String resultData, Bundle resultExtras) { + decrementPendingBroadcasts(); + } + + // this must be called while synchronized by callerin a synchronized block + // containing the sending of the broadcaset + private void incrementPendingBroadcastsLocked() { + if (mPendingBroadcasts++ == 0) { + synchronized (mLock) { + LocationManagerService.this.incrementPendingBroadcastsLocked(); + } + } + } + + private void decrementPendingBroadcasts() { + synchronized (this) { + if (--mPendingBroadcasts == 0) { + LocationManagerService.this.decrementPendingBroadcasts(); + } + } + } + } + + public void locationCallbackFinished(ILocationListener listener) { + Receiver receiver = getReceiver(listener); + if (receiver != null) { + receiver.decrementPendingBroadcasts(); } } @@ -722,29 +827,11 @@ public class LocationManagerService extends ILocationManager.Stub { for (int i=0; i<N; i++) { UpdateRecord record = records.get(i); // Sends a notification message to the receiver - try { - Receiver receiver = record.mReceiver; - if (receiver.isListener()) { - if (enabled) { - receiver.getListener().onProviderEnabled(provider); - } else { - receiver.getListener().onProviderDisabled(provider); - } - } else { - Intent providerIntent = new Intent(); - providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); - try { - receiver.getPendingIntent().send(mContext, 0, - providerIntent, null, null); - } catch (PendingIntent.CanceledException e) { - if (deadReceivers == null) { - deadReceivers = new ArrayList<Receiver>(); - deadReceivers.add(receiver); - } - } + if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { + if (deadReceivers == null) { + deadReceivers = new ArrayList<Receiver>(); + deadReceivers.add(record.mReceiver); } - } catch (RemoteException e) { - // The death link will clean this up. } listeners++; } @@ -958,15 +1045,8 @@ public class LocationManagerService extends ILocationManager.Stub { impl.enableLocationTracking(true); updateWakelockStatusLocked(); } else { - try { - // Notify the listener that updates are currently disabled - if (receiver.isListener()) { - receiver.getListener().onProviderDisabled(provider); - } - } catch(RemoteException e) { - Log.w(TAG, "RemoteException calling onProviderDisabled on " + - receiver.getListener()); - } + // Notify the listener that updates are currently disabled + receiver.callProviderEnabledLocked(provider, false); } } finally { Binder.restoreCallingIdentity(identity); @@ -1161,7 +1241,7 @@ public class LocationManagerService extends ILocationManager.Stub { } // Listener for receiving locations to trigger proximity alerts - class ProximityListener extends ILocationListener.Stub { + class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished { boolean isGpsAvailable = false; @@ -1198,7 +1278,14 @@ public class LocationManagerService extends ILocationManager.Stub { Intent enteredIntent = new Intent(); enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true); try { - intent.send(mContext, 0, enteredIntent, null, null); + synchronized (mLock) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + intent.send(mContext, 0, enteredIntent, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } } catch (PendingIntent.CanceledException e) { if (LOCAL_LOGV) { Log.v(TAG, "Canceled proximity alert: " + alert, e); @@ -1216,7 +1303,14 @@ public class LocationManagerService extends ILocationManager.Stub { Intent exitedIntent = new Intent(); exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false); try { - intent.send(mContext, 0, exitedIntent, null, null); + synchronized (mLock) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + intent.send(mContext, 0, exitedIntent, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } } catch (PendingIntent.CanceledException e) { if (LOCAL_LOGV) { Log.v(TAG, "Canceled proximity alert: " + alert, e); @@ -1269,6 +1363,11 @@ public class LocationManagerService extends ILocationManager.Stub { isGpsAvailable = false; } } + + public void onSendFinished(PendingIntent pendingIntent, Intent intent, + int resultCode, String resultData, Bundle resultExtras) { + decrementPendingBroadcasts(); + } } public void addProximityAlert(double latitude, double longitude, @@ -1306,19 +1405,20 @@ public class LocationManagerService extends ILocationManager.Stub { latitude, longitude, radius, expiration, intent); mProximityAlerts.put(intent, alert); - if (mProximityListener == null) { - mProximityListener = new Receiver(new ProximityListener()); + if (mProximityReceiver == null) { + mProximityListener = new ProximityListener(); + mProximityReceiver = new Receiver(mProximityListener); LocationProvider provider = LocationProviderImpl.getProvider( LocationManager.GPS_PROVIDER); if (provider != null) { - requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener); + requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver); } provider = LocationProviderImpl.getProvider(LocationManager.NETWORK_PROVIDER); if (provider != null) { - requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener); + requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver); } } } @@ -1342,7 +1442,8 @@ public class LocationManagerService extends ILocationManager.Stub { mProximityAlerts.remove(intent); if (mProximityAlerts.size() == 0) { - removeUpdatesLocked(mProximityListener); + removeUpdatesLocked(mProximityReceiver); + mProximityReceiver = null; mProximityListener = null; } } @@ -1585,35 +1686,7 @@ public class LocationManagerService extends ILocationManager.Stub { } handleLocationChangedLocked(location); - - if ((mWakeLockAcquireTime != 0) && - (SystemClock.elapsedRealtime() - mWakeLockAcquireTime - > MAX_TIME_FOR_WAKE_LOCK)) { - - removeMessages(MESSAGE_RELEASE_WAKE_LOCK); - - log("LocationWorkerHandler: Exceeded max time for wake lock"); - Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK); - sendMessageAtFrontOfQueue(m); - - } else if (mWakeLockAcquireTime != 0 && - mWakeLockGpsReceived && mWakeLockNetworkReceived) { - - removeMessages(MESSAGE_RELEASE_WAKE_LOCK); - - log("LocationWorkerHandler: Locations received."); - mWakeLockAcquireTime = 0; - Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK); - sendMessageDelayed(m, TIME_AFTER_WAKE_LOCK); - } - } - } else if (msg.what == MESSAGE_RELEASE_WAKE_LOCK) { - log("LocationWorkerHandler: Release"); - - // Update wakelock status so the next alarm is set before releasing wakelock - synchronized (mLock) { updateWakelockStatusLocked(); - releaseWakeLockLocked(); } } } catch (Exception e) { @@ -1727,7 +1800,7 @@ public class LocationManagerService extends ILocationManager.Stub { long callerId = Binder.clearCallingIdentity(); - boolean needsLock = false; + boolean needsLock = (mPendingBroadcasts > 0); long minTime = Integer.MAX_VALUE; if (mNetworkLocationProvider != null && mNetworkLocationProvider.isLocationTracking()) { @@ -1757,8 +1830,6 @@ public class LocationManagerService extends ILocationManager.Stub { log("No need for alarm"); mAlarmInterval = -1; - // Clear out existing wakelocks - mLocationHandler.removeMessages(MESSAGE_RELEASE_WAKE_LOCK); releaseWakeLockLocked(); } Binder.restoreCallingIdentity(callerId); @@ -1836,6 +1907,20 @@ public class LocationManagerService extends ILocationManager.Stub { } } + private void incrementPendingBroadcastsLocked() { + if (mPendingBroadcasts++ == 0) { + updateWakelockStatusLocked(); + } + } + + private void decrementPendingBroadcasts() { + synchronized (mLock) { + if (--mPendingBroadcasts == 0) { + updateWakelockStatusLocked(); + } + } + } + // Geocoder public String getFromLocation(double latitude, double longitude, int maxResults, @@ -2061,6 +2146,7 @@ public class LocationManagerService extends ILocationManager.Stub { i.dump(pw, " "); } } + pw.println(" mProximityReceiver=" + mProximityReceiver); pw.println(" mProximityListener=" + mProximityListener); if (mEnabledProviders.size() > 0) { pw.println(" Enabled Providers:"); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 9e062f4..159bc76 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -2932,11 +2932,12 @@ class PackageManagerService extends IPackageManager.Stub { } @Override - protected void dumpFilter(Printer out, String prefix, + protected void dumpFilter(PrintWriter out, String prefix, PackageParser.ActivityIntentInfo filter) { - out.println(prefix - + Integer.toHexString(System.identityHashCode(filter.activity)) - + " " + filter.activity.component.flattenToShortString()); + out.print(prefix); out.print( + Integer.toHexString(System.identityHashCode(filter.activity))); + out.print(' '); + out.println(filter.activity.componentShortName); } // List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) { @@ -3064,11 +3065,12 @@ class PackageManagerService extends IPackageManager.Stub { } @Override - protected void dumpFilter(Printer out, String prefix, + protected void dumpFilter(PrintWriter out, String prefix, PackageParser.ServiceIntentInfo filter) { - out.println(prefix - + Integer.toHexString(System.identityHashCode(filter.service)) - + " " + filter.service.component.flattenToShortString()); + out.print(prefix); out.print( + Integer.toHexString(System.identityHashCode(filter.service))); + out.print(' '); + out.println(filter.service.componentShortName); } // List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) { @@ -4578,80 +4580,83 @@ class PackageManagerService extends IPackageManager.Stub { return; } - Printer printer = new PrintWriterPrinter(pw); synchronized (mPackages) { pw.println("Activity Resolver Table:"); - mActivities.dump(printer, " "); + mActivities.dump(pw, " "); pw.println(" "); pw.println("Receiver Resolver Table:"); - mReceivers.dump(printer, " "); + mReceivers.dump(pw, " "); pw.println(" "); pw.println("Service Resolver Table:"); - mServices.dump(printer, " "); + mServices.dump(pw, " "); pw.println(" "); pw.println("Preferred Activities:"); - mSettings.mPreferredActivities.dump(printer, " "); + mSettings.mPreferredActivities.dump(pw, " "); pw.println(" "); pw.println("Preferred Packages:"); { for (PackageSetting ps : mSettings.mPreferredPackages) { - pw.println(" " + ps.name); + pw.print(" "); pw.println(ps.name); } } pw.println(" "); pw.println("Permissions:"); { for (BasePermission p : mSettings.mPermissions.values()) { - pw.println(" Permission [" + p.name + "] (" - + Integer.toHexString(System.identityHashCode(p)) - + "):"); - pw.println(" sourcePackage=" + p.sourcePackage); - pw.println(" uid=" + p.uid - + " gids=" + arrayToString(p.gids) - + " type=" + p.type); + pw.print(" Permission ["); pw.print(p.name); pw.print("] ("); + pw.print(Integer.toHexString(System.identityHashCode(p))); + pw.println("):"); + pw.print(" sourcePackage="); pw.println(p.sourcePackage); + pw.print(" uid="); pw.print(p.uid); + pw.print(" gids="); pw.print(arrayToString(p.gids)); + pw.print(" type="); pw.println(p.type); } } pw.println(" "); pw.println("Packages:"); { for (PackageSetting ps : mSettings.mPackages.values()) { - pw.println(" Package [" + ps.name + "] (" - + Integer.toHexString(System.identityHashCode(ps)) - + "):"); - pw.println(" userId=" + ps.userId - + " gids=" + arrayToString(ps.gids)); - pw.println(" sharedUser=" + ps.sharedUser); - pw.println(" pkg=" + ps.pkg); - pw.println(" codePath=" + ps.codePathString); - pw.println(" resourcePath=" + ps.resourcePathString); + pw.print(" Package ["); pw.print(ps.name); pw.print("] ("); + pw.print(Integer.toHexString(System.identityHashCode(ps))); + pw.println("):"); + pw.print(" userId="); pw.print(ps.userId); + pw.print(" gids="); pw.println(arrayToString(ps.gids)); + pw.print(" sharedUser="); pw.println(ps.sharedUser); + pw.print(" pkg="); pw.println(ps.pkg); + pw.print(" codePath="); pw.println(ps.codePathString); + pw.print(" resourcePath="); pw.println(ps.resourcePathString); if (ps.pkg != null) { - pw.println(" dataDir=" + ps.pkg.applicationInfo.dataDir); + pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); } - pw.println(" timeStamp=" + ps.getTimeStampStr()); - pw.println(" signatures=" + ps.signatures); - pw.println(" permissionsFixed=" + ps.permissionsFixed - + " pkgFlags=0x" + Integer.toHexString(ps.pkgFlags) - + " installStatus=" + ps.installStatus - + " enabled=" + ps.enabled); + pw.print(" timeStamp="); pw.println(ps.getTimeStampStr()); + pw.print(" signatures="); pw.println(ps.signatures); + pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed); + pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags)); + pw.print(" installStatus="); pw.print(ps.installStatus); + pw.print(" enabled="); pw.println(ps.enabled); if (ps.disabledComponents.size() > 0) { pw.println(" disabledComponents:"); for (String s : ps.disabledComponents) { - pw.println(" " + s); + pw.print(" "); pw.println(s); } } if (ps.enabledComponents.size() > 0) { pw.println(" enabledComponents:"); for (String s : ps.enabledComponents) { - pw.println(" " + s); + pw.print(" "); pw.println(s); } } - pw.println(" grantedPermissions:"); - for (String s : ps.grantedPermissions) { - pw.println(" " + s); + if (ps.grantedPermissions.size() > 0) { + pw.println(" grantedPermissions:"); + for (String s : ps.grantedPermissions) { + pw.print(" "); pw.println(s); + } } - pw.println(" loadedPermissions:"); - for (String s : ps.loadedPermissions) { - pw.println(" " + s); + if (ps.loadedPermissions.size() > 0) { + pw.println(" loadedPermissions:"); + for (String s : ps.loadedPermissions) { + pw.print(" "); pw.println(s); + } } } } @@ -4659,18 +4664,18 @@ class PackageManagerService extends IPackageManager.Stub { pw.println("Shared Users:"); { for (SharedUserSetting su : mSettings.mSharedUsers.values()) { - pw.println(" SharedUser [" + su.name + "] (" - + Integer.toHexString(System.identityHashCode(su)) - + "):"); - pw.println(" userId=" + su.userId - + " gids=" + arrayToString(su.gids)); + pw.print(" SharedUser ["); pw.print(su.name); pw.print("] ("); + pw.print(Integer.toHexString(System.identityHashCode(su))); + pw.println("):"); + pw.print(" userId="); pw.print(su.userId); + pw.print(" gids="); pw.println(arrayToString(su.gids)); pw.println(" grantedPermissions:"); for (String s : su.grantedPermissions) { - pw.println(" " + s); + pw.print(" "); pw.println(s); } pw.println(" loadedPermissions:"); for (String s : su.loadedPermissions) { - pw.println(" " + s); + pw.print(" "); pw.println(s); } } } @@ -5302,16 +5307,19 @@ class PackageManagerService extends IPackageManager.Stub { private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities = new IntentResolver<PreferredActivity, PreferredActivity>() { @Override - protected void dumpFilter(Printer out, String prefix, + protected void dumpFilter(PrintWriter out, String prefix, PreferredActivity filter) { - out.println(prefix - + Integer.toHexString(System.identityHashCode(filter)) - + " " + filter.mActivity.flattenToShortString() - + " match=0x" + Integer.toHexString(filter.mMatch)); + out.print(prefix); out.print( + Integer.toHexString(System.identityHashCode(filter))); + out.print(' '); + out.print(filter.mActivity.flattenToShortString()); + out.print(" match=0x"); + out.println( Integer.toHexString(filter.mMatch)); if (filter.mSetComponents != null) { - out.println(prefix + " Selected from:"); + out.print(prefix); out.println(" Selected from:"); for (int i=0; i<filter.mSetComponents.length; i++) { - out.println(prefix + " " + filter.mSetComponents[i]); + out.print(prefix); out.print(" "); + out.println(filter.mSetComponents[i]); } } } diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index b0fcb1c..321b17e 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -5175,6 +5175,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo final IInputContext mInputContext; final int mUid; final int mPid; + final String mStringName; SurfaceSession mSurfaceSession; int mNumWindow = 0; boolean mClientDead = false; @@ -5198,6 +5199,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo mInputContext = inputContext; mUid = Binder.getCallingUid(); mPid = Binder.getCallingPid(); + StringBuilder sb = new StringBuilder(); + sb.append("Session{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(" uid "); + sb.append(mUid); + sb.append("}"); + mStringName = sb.toString(); + synchronized (mWindowMap) { if (mInputMethodManager == null && mHaveInputMethods) { IBinder b = ServiceManager.getService( @@ -5377,20 +5386,24 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "mNumWindow=" + mNumWindow - + " mClientDead=" + mClientDead - + " mSurfaceSession=" + mSurfaceSession); - pw.println(prefix + "mPendingPointerWindow=" + mPendingPointerWindow - + " mPendingPointerMove=" + mPendingPointerMove); - pw.println(prefix + "mPendingTrackballWindow=" + mPendingTrackballWindow - + " mPendingTrackballMove=" + mPendingTrackballMove); + pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); + pw.print(" mClientDead="); pw.print(mClientDead); + pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); + if (mPendingPointerWindow != null || mPendingPointerMove != null) { + pw.print(prefix); + pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow); + pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove); + } + if (mPendingTrackballWindow != null || mPendingTrackballMove != null) { + pw.print(prefix); + pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow); + pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove); + } } @Override public String toString() { - return "Session{" - + Integer.toHexString(System.identityHashCode(this)) + "}"; + return mStringName; } } @@ -6458,67 +6471,114 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "mSession=" + mSession - + " mClient=" + mClient.asBinder()); - pw.println(prefix + "mAttrs=" + mAttrs); - pw.println(prefix + "mAttachedWindow=" + mAttachedWindow - + " mLayoutAttached=" + mLayoutAttached - + " mIsImWindow=" + mIsImWindow); - pw.println(prefix + "mBaseLayer=" + mBaseLayer - + " mSubLayer=" + mSubLayer - + " mAnimLayer=" + mLayer + "+" - + (mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment - : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)) - + "=" + mAnimLayer - + " mLastLayer=" + mLastLayer); - pw.println(prefix + "mSurface=" + mSurface); - pw.println(prefix + "mToken=" + mToken); - pw.println(prefix + "mRootToken=" + mRootToken); - pw.println(prefix + "mAppToken=" + mAppToken); - pw.println(prefix + "mTargetAppToken=" + mTargetAppToken); - pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility) - + " mPolicyVisibility=" + mPolicyVisibility - + " (after=" + mPolicyVisibilityAfterAnim - + ") mAttachedHidden=" + mAttachedHidden - + " mLastHidden=" + mLastHidden - + " mHaveFrame=" + mHaveFrame); - pw.println(prefix + "Requested w=" + mRequestedWidth + " h=" + mRequestedHeight - + " x=" + mReqXPos + " y=" + mReqYPos); - pw.println(prefix + "mGivenContentInsets=" + mGivenContentInsets.toShortString() - + " mGivenVisibleInsets=" + mGivenVisibleInsets.toShortString() - + " mTouchableInsets=" + mTouchableInsets - + " pending=" + mGivenInsetsPending); - pw.println(prefix + "mShownFrame=" + mShownFrame.toShortString() - + " last=" + mLastShownFrame.toShortString()); - pw.println(prefix + "mFrame=" + mFrame.toShortString() - + " last=" + mLastFrame.toShortString()); - pw.println(prefix + "mContainingFrame=" + mContainingFrame.toShortString() - + " mDisplayFrame=" + mDisplayFrame.toShortString()); - pw.println(prefix + "mContentFrame=" + mContentFrame.toShortString() - + " mVisibleFrame=" + mVisibleFrame.toShortString()); - pw.println(prefix + "mContentInsets=" + mContentInsets.toShortString() - + " last=" + mLastContentInsets.toShortString() - + " mVisibleInsets=" + mVisibleInsets.toShortString() - + " last=" + mLastVisibleInsets.toShortString()); - pw.println(prefix + "mShownAlpha=" + mShownAlpha - + " mAlpha=" + mAlpha + " mLastAlpha=" + mLastAlpha); - pw.println(prefix + "mAnimating=" + mAnimating - + " mLocalAnimating=" + mLocalAnimating - + " mAnimationIsEntrance=" + mAnimationIsEntrance - + " mAnimation=" + mAnimation); - pw.println(prefix + "XForm: has=" + mHasTransformation - + " " + mTransformation.toShortString()); - pw.println(prefix + "mDrawPending=" + mDrawPending - + " mCommitDrawPending=" + mCommitDrawPending - + " mReadyToShow=" + mReadyToShow - + " mHasDrawn=" + mHasDrawn); - pw.println(prefix + "mExiting=" + mExiting - + " mRemoveOnExit=" + mRemoveOnExit - + " mDestroying=" + mDestroying - + " mRemoved=" + mRemoved); - pw.println(prefix + "mOrientationChanging=" + mOrientationChanging - + " mAppFreezing=" + mAppFreezing); + StringBuilder sb = new StringBuilder(64); + + pw.print(prefix); pw.print("mSession="); pw.print(mSession); + pw.print(" mClient="); pw.println(mClient.asBinder()); + pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs); + if (mAttachedWindow != null || mLayoutAttached) { + pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow); + pw.print(" mLayoutAttached="); pw.println(mLayoutAttached); + } + if (mIsImWindow) { + pw.print(prefix); pw.print("mIsImWindow="); pw.println(mIsImWindow); + } + pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); + pw.print(" mSubLayer="); pw.print(mSubLayer); + pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+"); + pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment + : (mAppToken != null ? mAppToken.animLayerAdjustment : 0))); + pw.print("="); pw.print(mAnimLayer); + pw.print(" mLastLayer="); pw.println(mLastLayer); + if (mSurface != null) { + pw.print(prefix); pw.print("mSurface="); pw.println(mSurface); + } + pw.print(prefix); pw.print("mToken="); pw.println(mToken); + pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); + if (mAppToken != null) { + pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); + } + if (mTargetAppToken != null) { + pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken); + } + pw.print(prefix); pw.print("mViewVisibility=0x"); + pw.print(Integer.toHexString(mViewVisibility)); + pw.print(" mLastHidden="); pw.print(mLastHidden); + pw.print(" mHaveFrame="); pw.println(mHaveFrame); + if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) { + pw.print(prefix); pw.print("mPolicyVisibility="); + pw.print(mPolicyVisibility); + pw.print(" mPolicyVisibilityAfterAnim="); + pw.print(mPolicyVisibilityAfterAnim); + pw.print(" mAttachedHidden="); pw.println(mAttachedHidden); + } + pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth); + pw.print(" h="); pw.print(mRequestedHeight); + pw.print(" x="); pw.print(mReqXPos); + pw.print(" y="); pw.println(mReqYPos); + pw.print(prefix); pw.print("mGivenContentInsets="); + mGivenContentInsets.printShortString(pw); + pw.print(" mGivenVisibleInsets="); + mGivenVisibleInsets.printShortString(pw); + pw.println(); + if (mTouchableInsets != 0 || mGivenInsetsPending) { + pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets); + pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending); + } + pw.print(prefix); pw.print("mShownFrame="); + mShownFrame.printShortString(pw); + pw.print(" last="); mLastShownFrame.printShortString(pw); + pw.println(); + pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw); + pw.print(" last="); mLastFrame.printShortString(pw); + pw.println(); + pw.print(prefix); pw.print("mContainingFrame="); + mContainingFrame.printShortString(pw); + pw.print(" mDisplayFrame="); + mDisplayFrame.printShortString(pw); + pw.println(); + pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw); + pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw); + pw.println(); + pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw); + pw.print(" last="); mLastContentInsets.printShortString(pw); + pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw); + pw.print(" last="); mLastVisibleInsets.printShortString(pw); + pw.println(); + if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { + pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); + pw.print(" mAlpha="); pw.print(mAlpha); + pw.print(" mLastAlpha="); pw.println(mLastAlpha); + } + if (mAnimating || mLocalAnimating || mAnimationIsEntrance + || mAnimation != null) { + pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating); + pw.print(" mLocalAnimating="); pw.print(mLocalAnimating); + pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); + pw.print(" mAnimation="); pw.println(mAnimation); + } + if (mHasTransformation || mHasLocalTransformation) { + pw.print(prefix); pw.print("XForm: has="); + pw.print(mHasTransformation); + pw.print(" hasLocal="); pw.print(mHasLocalTransformation); + pw.print(" "); mTransformation.printShortString(pw); + pw.println(); + } + pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending); + pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending); + pw.print(" mReadyToShow="); pw.print(mReadyToShow); + pw.print(" mHasDrawn="); pw.println(mHasDrawn); + if (mExiting || mRemoveOnExit || mDestroying || mRemoved) { + pw.print(prefix); pw.print("mExiting="); pw.print(mExiting); + pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit); + pw.print(" mDestroying="); pw.print(mDestroying); + pw.print(" mRemoved="); pw.println(mRemoved); + } + if (mOrientationChanging || mAppFreezing) { + pw.print(prefix); pw.print("mOrientationChanging="); + pw.print(mOrientationChanging); + pw.print(" mAppFreezing="); pw.println(mAppFreezing); + } } @Override @@ -6544,6 +6604,9 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo // not be removed when all windows are removed. final boolean explicit; + // For printing. + String stringName; + // If this is an AppWindowToken, this is non-null. AppWindowToken appWindowToken; @@ -6566,18 +6629,23 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "token=" + token); - pw.println(prefix + "windows=" + windows); - pw.println(prefix + "windowType=" + windowType + " hidden=" + hidden - + " hasVisible=" + hasVisible); + pw.print(prefix); pw.print("token="); pw.println(token); + pw.print(prefix); pw.print("windows="); pw.println(windows); + pw.print(prefix); pw.print("windowType="); pw.print(windowType); + pw.print(" hidden="); pw.print(hidden); + pw.print(" hasVisible="); pw.println(hasVisible); } @Override public String toString() { - return "WindowToken{" - + Integer.toHexString(System.identityHashCode(this)) - + " token=" + token + "}"; + if (stringName == null) { + StringBuilder sb = new StringBuilder(); + sb.append("WindowToken{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(" token="); sb.append(token); sb.append('}'); + stringName = sb.toString(); + } + return stringName; } }; @@ -6865,38 +6933,66 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo void dump(PrintWriter pw, String prefix) { super.dump(pw, prefix); - pw.println(prefix + "app=" + (appToken != null)); - pw.println(prefix + "allAppWindows=" + allAppWindows); - pw.println(prefix + "groupId=" + groupId - + " requestedOrientation=" + requestedOrientation); - pw.println(prefix + "hiddenRequested=" + hiddenRequested - + " clientHidden=" + clientHidden - + " willBeHidden=" + willBeHidden - + " reportedVisible=" + reportedVisible); - pw.println(prefix + "paused=" + paused - + " freezingScreen=" + freezingScreen); - pw.println(prefix + "numInterestingWindows=" + numInterestingWindows - + " numDrawnWindows=" + numDrawnWindows - + " inPendingTransaction=" + inPendingTransaction - + " allDrawn=" + allDrawn); - pw.println(prefix + "animating=" + animating - + " animation=" + animation); - pw.println(prefix + "animLayerAdjustment=" + animLayerAdjustment - + " transformation=" + transformation.toShortString()); - pw.println(prefix + "startingData=" + startingData - + " removed=" + removed - + " firstWindowDrawn=" + firstWindowDrawn); - pw.println(prefix + "startingWindow=" + startingWindow - + " startingView=" + startingView - + " startingDisplayed=" + startingDisplayed - + " startingMoved" + startingMoved); + if (appToken != null) { + pw.print(prefix); pw.println("app=true"); + } + if (allAppWindows.size() > 0) { + pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows); + } + pw.print(prefix); pw.print("groupId="); pw.print(groupId); + pw.print(" requestedOrientation="); pw.println(requestedOrientation); + pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested); + pw.print(" clientHidden="); pw.print(clientHidden); + pw.print(" willBeHidden="); pw.print(willBeHidden); + pw.print(" reportedVisible="); pw.println(reportedVisible); + if (paused || freezingScreen) { + pw.print(prefix); pw.print("paused="); pw.print(paused); + pw.print(" freezingScreen="); pw.println(freezingScreen); + } + if (numInterestingWindows != 0 || numDrawnWindows != 0 + || inPendingTransaction || allDrawn) { + pw.print(prefix); pw.print("numInterestingWindows="); + pw.print(numInterestingWindows); + pw.print(" numDrawnWindows="); pw.print(numDrawnWindows); + pw.print(" inPendingTransaction="); pw.print(inPendingTransaction); + pw.print(" allDrawn="); pw.println(allDrawn); + } + if (animating || animation != null) { + pw.print(prefix); pw.print("animating="); pw.print(animating); + pw.print(" animation="); pw.println(animation); + } + if (animLayerAdjustment != 0) { + pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment); + } + if (hasTransformation) { + pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation); + pw.print(" transformation="); transformation.printShortString(pw); + pw.println(); + } + if (startingData != null || removed || firstWindowDrawn) { + pw.print(prefix); pw.print("startingData="); pw.print(startingData); + pw.print(" removed="); pw.print(removed); + pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn); + } + if (startingWindow != null || startingView != null + || startingDisplayed || startingMoved) { + pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow); + pw.print(" startingView="); pw.print(startingView); + pw.print(" startingDisplayed="); pw.print(startingDisplayed); + pw.print(" startingMoved"); pw.println(startingMoved); + } } @Override public String toString() { - return "AppWindowToken{" - + Integer.toHexString(System.identityHashCode(this)) - + " token=" + token + "}"; + if (stringName == null) { + StringBuilder sb = new StringBuilder(); + sb.append("AppWindowToken{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(" token="); sb.append(token); sb.append('}'); + stringName = sb.toString(); + } + return stringName; } } @@ -8652,7 +8748,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println("Current Window Manager state:"); for (int i=mWindows.size()-1; i>=0; i--) { WindowState w = (WindowState)mWindows.get(i); - pw.println(" Window #" + i + ":"); + pw.print(" Window #"); pw.print(i); pw.print(' '); + pw.print(w); pw.println(":"); w.dump(pw, " "); } if (mInputMethodDialogs.size() > 0) { @@ -8660,7 +8757,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" Input method dialogs:"); for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { WindowState w = mInputMethodDialogs.get(i); - pw.println(" IM Dialog #" + i + ": " + w); + pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); } } if (mPendingRemove.size() > 0) { @@ -8668,7 +8765,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" Remove pending for:"); for (int i=mPendingRemove.size()-1; i>=0; i--) { WindowState w = mPendingRemove.get(i); - pw.println(" Remove #" + i + ":"); + pw.print(" Remove #"); pw.print(i); pw.print(' '); + pw.print(w); pw.println(":"); w.dump(pw, " "); } } @@ -8677,7 +8775,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" Windows force removing:"); for (int i=mForceRemoves.size()-1; i>=0; i--) { WindowState w = mForceRemoves.get(i); - pw.println(" Removing #" + i + ":"); + pw.print(" Removing #"); pw.print(i); pw.print(' '); + pw.print(w); pw.println(":"); w.dump(pw, " "); } } @@ -8686,7 +8785,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" Windows waiting to destroy their surface:"); for (int i=mDestroySurface.size()-1; i>=0; i--) { WindowState w = mDestroySurface.get(i); - pw.println(" Destroy #" + i + ":"); + pw.print(" Destroy #"); pw.print(i); pw.print(' '); + pw.print(w); pw.println(":"); w.dump(pw, " "); } } @@ -8695,7 +8795,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" Windows losing focus:"); for (int i=mLosingFocus.size()-1; i>=0; i--) { WindowState w = mLosingFocus.get(i); - pw.println(" Losing #" + i + ":"); + pw.print(" Losing #"); pw.print(i); pw.print(' '); + pw.print(w); pw.println(":"); w.dump(pw, " "); } } @@ -8705,7 +8806,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo Iterator<Session> it = mSessions.iterator(); while (it.hasNext()) { Session s = it.next(); - pw.println(" Session " + s); + pw.print(" Session "); pw.print(s); pw.println(':'); s.dump(pw, " "); } } @@ -8715,7 +8816,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo Iterator<WindowToken> it = mTokenMap.values().iterator(); while (it.hasNext()) { WindowToken token = it.next(); - pw.println(" Token " + token.token); + pw.print(" Token "); pw.print(token.token); pw.println(':'); token.dump(pw, " "); } } @@ -8723,14 +8824,16 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" "); pw.println(" Window token list:"); for (int i=0; i<mTokenList.size(); i++) { - pw.println(" WindowToken #" + i + ": " + mTokenList.get(i)); + pw.print(" #"); pw.print(i); pw.print(": "); + pw.println(mTokenList.get(i)); } } if (mAppTokens.size() > 0) { pw.println(" "); pw.println(" Application tokens in Z order:"); for (int i=mAppTokens.size()-1; i>=0; i--) { - pw.println(" AppWindowToken #" + i + ": " + mAppTokens.get(i)); + pw.print(" App #"); pw.print(i); pw.print(": "); + pw.println(mAppTokens.get(i)); } } if (mFinishedStarting.size() > 0) { @@ -8738,7 +8841,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" Finishing start of application tokens:"); for (int i=mFinishedStarting.size()-1; i>=0; i--) { WindowToken token = mFinishedStarting.get(i); - pw.println(" Finish Starting App Token #" + i + ":"); + pw.print(" Finished Starting #"); pw.print(i); + pw.print(' '); pw.print(token); pw.println(':'); token.dump(pw, " "); } } @@ -8747,7 +8851,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" Exiting tokens:"); for (int i=mExitingTokens.size()-1; i>=0; i--) { WindowToken token = mExitingTokens.get(i); - pw.println(" Exiting Token #" + i + ":"); + pw.print(" Exiting #"); pw.print(i); + pw.print(' '); pw.print(token); pw.println(':'); token.dump(pw, " "); } } @@ -8756,54 +8861,59 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.println(" Exiting application tokens:"); for (int i=mExitingAppTokens.size()-1; i>=0; i--) { WindowToken token = mExitingAppTokens.get(i); - pw.println(" Exiting App Token #" + i + ":"); + pw.print(" Exiting App #"); pw.print(i); + pw.print(' '); pw.print(token); pw.println(':'); token.dump(pw, " "); } } pw.println(" "); - pw.println(" mCurrentFocus=" + mCurrentFocus); - pw.println(" mLastFocus=" + mLastFocus); - pw.println(" mFocusedApp=" + mFocusedApp); - pw.println(" mInputMethodTarget=" + mInputMethodTarget); - pw.println(" mInputMethodWindow=" + mInputMethodWindow); - pw.println(" mInTouchMode=" + mInTouchMode); - pw.println(" mSystemBooted=" + mSystemBooted - + " mDisplayEnabled=" + mDisplayEnabled); - pw.println(" mLayoutNeeded=" + mLayoutNeeded - + " mBlurShown=" + mBlurShown); - pw.println(" mDimShown=" + mDimShown - + " current=" + mDimCurrentAlpha - + " target=" + mDimTargetAlpha - + " delta=" + mDimDeltaPerMs - + " lastAnimTime=" + mLastDimAnimTime); - pw.println(" mInputMethodAnimLayerAdjustment=" - + mInputMethodAnimLayerAdjustment); - pw.println(" mDisplayFrozen=" + mDisplayFrozen - + " mWindowsFreezingScreen=" + mWindowsFreezingScreen - + " mAppsFreezingScreen=" + mAppsFreezingScreen); - pw.println(" mRotation=" + mRotation - + ", mForcedAppOrientation=" + mForcedAppOrientation - + ", mRequestedRotation=" + mRequestedRotation); - pw.println(" mAnimationPending=" + mAnimationPending - + " mWindowAnimationScale=" + mWindowAnimationScale - + " mTransitionWindowAnimationScale=" + mTransitionAnimationScale); - pw.println(" mNextAppTransition=0x" - + Integer.toHexString(mNextAppTransition) - + ", mAppTransitionReady=" + mAppTransitionReady - + ", mAppTransitionTimeout=" + mAppTransitionTimeout); - pw.println(" mStartingIconInTransition=" + mStartingIconInTransition - + ", mSkipAppTransitionAnimation=" + mSkipAppTransitionAnimation); - pw.println(" mOpeningApps=" + mOpeningApps); - pw.println(" mClosingApps=" + mClosingApps); - pw.println(" DisplayWidth=" + mDisplay.getWidth() - + " DisplayHeight=" + mDisplay.getHeight()); + pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); + pw.print(" mLastFocus="); pw.println(mLastFocus); + pw.print(" mFocusedApp="); pw.println(mFocusedApp); + pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); + pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); + pw.print(" mInTouchMode="); pw.println(mInTouchMode); + pw.print(" mSystemBooted="); pw.print(mSystemBooted); + pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); + pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); + pw.print(" mBlurShown="); pw.println(mBlurShown); + pw.print(" mDimShown="); pw.print(mDimShown); + pw.print(" current="); pw.print(mDimCurrentAlpha); + pw.print(" target="); pw.print(mDimTargetAlpha); + pw.print(" delta="); pw.print(mDimDeltaPerMs); + pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); + pw.print(" mInputMethodAnimLayerAdjustment="); + pw.println(mInputMethodAnimLayerAdjustment); + pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); + pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); + pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen); + pw.print(" mRotation="); pw.print(mRotation); + pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation); + pw.print(", mRequestedRotation="); pw.println(mRequestedRotation); + pw.print(" mAnimationPending="); pw.print(mAnimationPending); + pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); + pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale); + pw.print(" mNextAppTransition=0x"); + pw.print(Integer.toHexString(mNextAppTransition)); + pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady); + pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout); + pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); + pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); + if (mOpeningApps.size() > 0) { + pw.print(" mOpeningApps="); pw.println(mOpeningApps); + } + if (mClosingApps.size() > 0) { + pw.print(" mClosingApps="); pw.println(mClosingApps); + } + pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth()); + pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight()); pw.println(" KeyWaiter state:"); - pw.println(" mLastWin=" + mKeyWaiter.mLastWin - + " mLastBinder=" + mKeyWaiter.mLastBinder); - pw.println(" mFinished=" + mKeyWaiter.mFinished - + " mGotFirstWindow=" + mKeyWaiter.mGotFirstWindow - + " mEventDispatching=" + mKeyWaiter.mEventDispatching - + " mTimeToSwitch=" + mKeyWaiter.mTimeToSwitch); + pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin); + pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder); + pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished); + pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow); + pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching); + pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch); } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index a3c23d3..b04f5a8 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -7890,24 +7890,24 @@ public final class ActivityManagerService extends ActivityManagerNative implemen return; } pw.println("Activities in Current Activity Manager State:"); - dumpHistoryList(pw, mHistory, " ", "History", true); + dumpHistoryList(pw, mHistory, " ", "Hist", true); pw.println(" "); pw.println(" Running activities (most recent first):"); - dumpHistoryList(pw, mLRUActivities, " ", "Running", false); + dumpHistoryList(pw, mLRUActivities, " ", "Run", false); if (mWaitingVisibleActivities.size() > 0) { pw.println(" "); pw.println(" Activities waiting for another to become visible:"); - dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Waiting", false); + dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false); } if (mStoppingActivities.size() > 0) { pw.println(" "); pw.println(" Activities waiting to stop:"); - dumpHistoryList(pw, mStoppingActivities, " ", "Stopping", false); + dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false); } if (mFinishingActivities.size() > 0) { pw.println(" "); pw.println(" Activities waiting to finish:"); - dumpHistoryList(pw, mFinishingActivities, " ", "Finishing", false); + dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false); } pw.println(" "); @@ -7922,7 +7922,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen final int N = mRecentTasks.size(); for (int i=0; i<N; i++) { - pw.println(" Recent Task #" + i); + TaskRecord tr = mRecentTasks.get(i); + pw.print(" * Recent #"); pw.print(i); pw.print(": "); + pw.println(tr); mRecentTasks.get(i).dump(pw, " "); } } @@ -7944,8 +7946,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen needSep = true; } ProcessRecord r = procs.valueAt(ia); - pw.print(r.persistent ? " *PERSISTENT* Process [" : " Process ["); - pw.print(r.processName); pw.print("] UID "); pw.println(procs.keyAt(ia)); + pw.print(r.persistent ? " *PERS*" : " *APP*"); + pw.print(" UID "); pw.print(procs.keyAt(ia)); + pw.print(" "); pw.println(r); r.dump(pw, " "); if (r.persistent) { numPers++; @@ -7958,7 +7961,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen needSep = true; pw.println(" Running processes (most recent first):"); dumpProcessList(pw, mLRUProcesses, " ", - "Running Norm Proc", "Running PERS Proc", true); + "App ", "PERS", true); needSep = true; } @@ -7968,8 +7971,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen needSep = true; pw.println(" PID mappings:"); for (int i=0; i<mPidsSelfLocked.size(); i++) { - pw.println(" PID #" + mPidsSelfLocked.keyAt(i) - + ": " + mPidsSelfLocked.valueAt(i)); + pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i)); + pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i)); } } } @@ -7979,8 +7982,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen needSep = true; pw.println(" Foreground Processes:"); for (int i=0; i<mForegroundProcesses.size(); i++) { - pw.println(" PID #" + mForegroundProcesses.keyAt(i) - + ": " + mForegroundProcesses.valueAt(i)); + pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i)); + pw.print(": "); pw.println(mForegroundProcesses.valueAt(i)); } } @@ -7989,7 +7992,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen needSep = true; pw.println(" Persisent processes that are starting:"); dumpProcessList(pw, mPersistentStartingProcesses, " ", - "Starting Initial Proc", "Restarting PERS Proc", false); + "Starting Norm", "Restarting PERS", false); } if (mStartingProcesses.size() > 0) { @@ -7997,7 +8000,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen needSep = true; pw.println(" Processes that are starting:"); dumpProcessList(pw, mStartingProcesses, " ", - "Starting Norm Proc", "Starting PERS Proc", false); + "Starting Norm", "Starting PERS", false); } if (mRemovedProcesses.size() > 0) { @@ -8005,7 +8008,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen needSep = true; pw.println(" Processes that are being removed:"); dumpProcessList(pw, mRemovedProcesses, " ", - "Removed Norm Proc", "Removed PERS Proc", false); + "Removed Norm", "Removed PERS", false); } if (mProcessesOnHold.size() > 0) { @@ -8013,7 +8016,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen needSep = true; pw.println(" Processes that are on old until the system is ready:"); dumpProcessList(pw, mProcessesOnHold, " ", - "OnHold Norm Proc", "OnHold PERS Proc", false); + "OnHold Norm", "OnHold PERS", false); } if (mProcessCrashTimes.getMap().size() > 0) { @@ -8026,10 +8029,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen SparseArray<Long> uids = procs.getValue(); final int N = uids.size(); for (int i=0; i<N; i++) { - pw.println(" Process " + procs.getKey() - + " uid " + uids.keyAt(i) - + ": last crashed " - + (now-uids.valueAt(i)) + " ms ago"); + pw.print(" Process "); pw.print(procs.getKey()); + pw.print(" uid "); pw.print(uids.keyAt(i)); + pw.print(": last crashed "); + pw.print((now-uids.valueAt(i))); + pw.println(" ms ago"); } } } @@ -8043,9 +8047,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen SparseArray<Long> uids = procs.getValue(); final int N = uids.size(); for (int i=0; i<N; i++) { - pw.println(" Bad process " + procs.getKey() - + " uid " + uids.keyAt(i) - + ": crashed at time " + uids.valueAt(i)); + pw.print(" Bad process "); pw.print(procs.getKey()); + pw.print(" uid "); pw.print(uids.keyAt(i)); + pw.print(": crashed at time "); + pw.println(uids.valueAt(i)); } } } @@ -8144,14 +8149,14 @@ public final class ActivityManagerService extends ActivityManagerNative implemen Iterator it = mRegisteredReceivers.values().iterator(); while (it.hasNext()) { ReceiverList r = (ReceiverList)it.next(); - pw.println(" Receiver " + r.receiver); + pw.print(" * "); pw.println(r); r.dump(pw, " "); } } pw.println(" "); pw.println("Receiver Resolver Table:"); - mReceiverResolver.dump(new PrintWriterPrinter(pw), " "); + mReceiverResolver.dump(pw, " "); if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0 || mPendingBroadcast != null) { @@ -8185,13 +8190,23 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (mStickyBroadcasts != null) { pw.println(" "); pw.println(" Sticky broadcasts:"); + StringBuilder sb = new StringBuilder(128); for (Map.Entry<String, ArrayList<Intent>> ent : mStickyBroadcasts.entrySet()) { - pw.println(" Sticky action " + ent.getKey() + ":"); + pw.print(" * Sticky action "); pw.print(ent.getKey()); + pw.println(":"); ArrayList<Intent> intents = ent.getValue(); final int N = intents.size(); for (int i=0; i<N; i++) { - pw.println(" " + intents.get(i)); + sb.setLength(0); + sb.append(" Intent: "); + intents.get(i).toShortString(sb, true, false); + pw.println(sb.toString()); + Bundle bundle = intents.get(i).getExtras(); + if (bundle != null) { + pw.print(" "); + pw.println(bundle.toString()); + } } } } @@ -8222,7 +8237,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen Iterator<ServiceRecord> it = mServices.values().iterator(); while (it.hasNext()) { ServiceRecord r = it.next(); - pw.println(" Service " + r.shortName); + pw.print(" * "); pw.println(r); r.dump(pw, " "); } needSep = true; @@ -8233,7 +8248,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen pw.println(" Pending services:"); for (int i=0; i<mPendingServices.size(); i++) { ServiceRecord r = mPendingServices.get(i); - pw.println(" Pending Service " + r.shortName); + pw.print(" * Pending "); pw.println(r); r.dump(pw, " "); } needSep = true; @@ -8244,7 +8259,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen pw.println(" Restarting services:"); for (int i=0; i<mRestartingServices.size(); i++) { ServiceRecord r = mRestartingServices.get(i); - pw.println(" Restarting Service " + r.shortName); + pw.print(" * Restarting "); pw.println(r); r.dump(pw, " "); } needSep = true; @@ -8255,7 +8270,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen pw.println(" Stopping services:"); for (int i=0; i<mStoppingServices.size(); i++) { ServiceRecord r = mStoppingServices.get(i); - pw.println(" Stopping Service " + r.shortName); + pw.print(" * Stopping "); pw.println(r); r.dump(pw, " "); } needSep = true; @@ -8268,8 +8283,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen = mServiceConnections.values().iterator(); while (it.hasNext()) { ConnectionRecord r = it.next(); - pw.println(" " + r.binding.service.shortName - + " -> " + r.conn.asBinder()); + pw.print(" * "); pw.println(r); r.dump(pw, " "); } } @@ -8292,27 +8306,28 @@ public final class ActivityManagerService extends ActivityManagerNative implemen boolean needSep = false; - if (mProvidersByName.size() > 0) { - pw.println(" Published content providers (by name):"); - Iterator it = mProvidersByName.entrySet().iterator(); + if (mProvidersByClass.size() > 0) { + if (needSep) pw.println(" "); + pw.println(" Published content providers (by class):"); + Iterator it = mProvidersByClass.entrySet().iterator(); while (it.hasNext()) { Map.Entry e = (Map.Entry)it.next(); ContentProviderRecord r = (ContentProviderRecord)e.getValue(); - pw.println(" Provider " + (String)e.getKey()); + pw.print(" * "); pw.println(r); r.dump(pw, " "); } needSep = true; } - if (mProvidersByClass.size() > 0) { - if (needSep) pw.println(" "); - pw.println(" Published content providers (by class):"); - Iterator it = mProvidersByClass.entrySet().iterator(); + if (mProvidersByName.size() > 0) { + pw.println(" "); + pw.println(" Authority to provider mappings:"); + Iterator it = mProvidersByName.entrySet().iterator(); while (it.hasNext()) { Map.Entry e = (Map.Entry)it.next(); ContentProviderRecord r = (ContentProviderRecord)e.getValue(); - pw.println(" Provider " + (String)e.getKey()); - r.dump(pw, " "); + pw.print(" "); pw.print(e.getKey()); pw.print(": "); + pw.println(r); } needSep = true; } @@ -8321,21 +8336,25 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (needSep) pw.println(" "); pw.println(" Launching content providers:"); for (int i=mLaunchingProviders.size()-1; i>=0; i--) { - pw.println(" Provider #" + i + ":"); - ((ContentProviderRecord)mLaunchingProviders.get(i)).dump(pw, " "); + pw.print(" Launching #"); pw.print(i); pw.print(": "); + pw.println(mLaunchingProviders.get(i)); } needSep = true; } - pw.println(); - pw.println("Granted Uri Permissions:"); - for (int i=0; i<mGrantedUriPermissions.size(); i++) { - int uid = mGrantedUriPermissions.keyAt(i); - HashMap<Uri, UriPermission> perms - = mGrantedUriPermissions.valueAt(i); - pw.println(" Uris granted to uid " + uid + ":"); - for (UriPermission perm : perms.values()) { - perm.dump(pw, " "); + if (mGrantedUriPermissions.size() > 0) { + pw.println(); + pw.println("Granted Uri Permissions:"); + for (int i=0; i<mGrantedUriPermissions.size(); i++) { + int uid = mGrantedUriPermissions.keyAt(i); + HashMap<Uri, UriPermission> perms + = mGrantedUriPermissions.valueAt(i); + pw.print(" * UID "); pw.print(uid); + pw.println(" holds:"); + for (UriPermission perm : perms.values()) { + pw.print(" "); pw.println(perm); + perm.dump(pw, " "); + } } } } @@ -8353,7 +8372,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen return; } - pw.println("Intent Senders in Current Activity Manager State:"); + pw.println("Pending Intents in Current Activity Manager State:"); if (this.mIntentSenderRecords.size() > 0) { Iterator<WeakReference<PendingIntentRecord>> it @@ -8362,10 +8381,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen WeakReference<PendingIntentRecord> ref = it.next(); PendingIntentRecord rec = ref != null ? ref.get(): null; if (rec != null) { - pw.println(" IntentSender " + rec); + pw.print(" * "); pw.println(rec); rec.dump(pw, " "); } else { - pw.println(" IntentSender " + ref); + pw.print(" * "); pw.print(ref); } } } @@ -8377,24 +8396,21 @@ public final class ActivityManagerService extends ActivityManagerNative implemen TaskRecord lastTask = null; for (int i=list.size()-1; i>=0; i--) { HistoryRecord r = (HistoryRecord)list.get(i); + final boolean full = complete || !r.inHistory; if (lastTask != r.task) { lastTask = r.task; - if (complete || !r.inHistory) { + pw.print(prefix); + pw.print(full ? "* " : " "); + pw.println(lastTask); + if (full) { lastTask.dump(pw, prefix + " "); - } else { - pw.print(prefix); - pw.print(" "); - pw.println(lastTask); } } - if (complete || !r.inHistory) { - pw.print(prefix); pw.print(" "); pw.print(label); - pw.print(" #"); pw.print(i); pw.println(":"); + pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label); + pw.print(" #"); pw.print(i); pw.print(": "); + pw.println(r); + if (full) { r.dump(pw, prefix + " "); - } else { - pw.print(prefix); pw.print(" "); pw.print(label); - pw.print(" #"); pw.print(i); pw.print(": "); - pw.println(r); } } } diff --git a/services/java/com/android/server/am/AppBindRecord.java b/services/java/com/android/server/am/AppBindRecord.java index ce6f6dc..9c57360 100644 --- a/services/java/com/android/server/am/AppBindRecord.java +++ b/services/java/com/android/server/am/AppBindRecord.java @@ -32,9 +32,12 @@ class AppBindRecord { // All ConnectionRecord for this client. void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); pw.println(prefix + "service=" + service); pw.println(prefix + "client=" + client); + dumpInIntentBind(pw, prefix); + } + + void dumpInIntentBind(PrintWriter pw, String prefix) { if (connections.size() > 0) { pw.println(prefix + "Per-process Connections:"); Iterator<ConnectionRecord> it = connections.iterator(); diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index e265f43..ddc3e68 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -302,7 +302,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } if (isCheckin) mStats.dumpCheckinLocked(pw, args); - else mStats.dumpLocked(new PrintWriterPrinter(pw)); + else mStats.dumpLocked(pw); } } } diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java index cd7f720..0eeb393 100644 --- a/services/java/com/android/server/am/BroadcastFilter.java +++ b/services/java/com/android/server/am/BroadcastFilter.java @@ -18,6 +18,7 @@ package com.android.server.am; import android.content.IntentFilter; import android.util.PrintWriterPrinter; +import android.util.Printer; import java.io.PrintWriter; @@ -33,19 +34,25 @@ class BroadcastFilter extends IntentFilter { requiredPermission = _requiredPermission; } - public void dumpLocal(PrintWriter pw, String prefix) { - super.dump(new PrintWriterPrinter(pw), prefix); - } - public void dump(PrintWriter pw, String prefix) { - dumpLocal(pw, prefix); - pw.println(prefix + "requiredPermission=" + requiredPermission); + dumpInReceiverList(pw, new PrintWriterPrinter(pw), prefix); receiverList.dumpLocal(pw, prefix); } + public void dumpInReceiverList(PrintWriter pw, Printer pr, String prefix) { + super.dump(pr, prefix); + if (requiredPermission != null) { + pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission); + } + } + public String toString() { - return "BroadcastFilter{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + receiverList + "}"; + StringBuilder sb = new StringBuilder(); + sb.append("BroadcastFilter{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(' '); + sb.append(receiverList); + sb.append('}'); + return sb.toString(); } } diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java index b4c7df1..b3343dd 100644 --- a/services/java/com/android/server/am/ConnectionRecord.java +++ b/services/java/com/android/server/am/ConnectionRecord.java @@ -31,9 +31,10 @@ class ConnectionRecord { String stringName; // Caching of toString. void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); pw.println(prefix + "binding=" + binding); - pw.println(prefix + "activity=" + activity); + if (activity != null) { + pw.println(prefix + "activity=" + activity); + } pw.println(prefix + "conn=" + conn.asBinder() + " flags=0x" + Integer.toHexString(flags)); } diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java index 2b9e006..c764635 100644 --- a/services/java/com/android/server/am/ContentProviderRecord.java +++ b/services/java/com/android/server/am/ContentProviderRecord.java @@ -54,19 +54,27 @@ class ContentProviderRecord extends ContentProviderHolder { } void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "package=" + info.applicationInfo.packageName - + " process=" + info.processName); - pw.println(prefix + "app=" + app); - pw.println(prefix + "launchingApp=" + launchingApp); - pw.println(prefix + "provider=" + provider); - pw.println(prefix + "name=" + info.authority); - pw.println(prefix + "isSyncable=" + info.isSyncable); - pw.println(prefix + "multiprocess=" + info.multiprocess - + " initOrder=" + info.initOrder - + " uid=" + uid); - pw.println(prefix + "clients=" + clients); - pw.println(prefix + "externals=" + externals); + pw.print(prefix); pw.print("package="); + pw.print(info.applicationInfo.packageName); + pw.print("process="); pw.println(info.processName); + pw.print(prefix); pw.print("app="); pw.println(app); + if (launchingApp != null) { + pw.print(prefix); pw.print("launchingApp="); pw.println(launchingApp); + } + pw.print(prefix); pw.print("uid="); pw.print(uid); + pw.print(" provider="); pw.println(provider); + pw.print(prefix); pw.print("name="); pw.println(info.authority); + if (info.isSyncable || info.multiprocess || info.initOrder != 0) { + pw.print(prefix); pw.print("isSyncable="); pw.print(info.isSyncable); + pw.print("multiprocess="); pw.print(info.multiprocess); + pw.print(" initOrder="); pw.println(info.initOrder); + } + if (clients.size() > 0) { + pw.print(prefix); pw.print("clients="); pw.println(clients); + } + if (externals != 0) { + pw.print(prefix); pw.print("externals="); pw.println(externals); + } } public String toString() { diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java index a2fd62b..1488791 100644 --- a/services/java/com/android/server/am/HistoryRecord.java +++ b/services/java/com/android/server/am/HistoryRecord.java @@ -103,7 +103,6 @@ class HistoryRecord extends IApplicationToken.Stub { String stringName; // for caching of toString(). void dump(PrintWriter pw, String prefix) { - pw.print(prefix); pw.println(this); pw.print(prefix); pw.print("packageName="); pw.print(packageName); pw.print(" processName="); pw.println(processName); pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid); @@ -112,9 +111,10 @@ class HistoryRecord extends IApplicationToken.Stub { pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask); pw.print(" task="); pw.println(task); pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity); - pw.print(prefix); pw.print("realActivity="); pw.println(realActivity); - pw.print(prefix); pw.print("dir="); pw.print(baseDir); - pw.print(" res="); pw.print(resDir); + pw.print(prefix); pw.print("realActivity="); + pw.println(realActivity.flattenToShortString()); + pw.print(prefix); pw.print("base="); pw.print(baseDir); + if (!resDir.equals(baseDir)) pw.print(" res="); pw.print(resDir); pw.print(" data="); pw.println(dataDir); pw.print(prefix); pw.print("labelRes=0x"); pw.print(Integer.toHexString(labelRes)); @@ -504,7 +504,7 @@ class HistoryRecord extends IApplicationToken.Stub { sb.append("HistoryRecord{"); sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(' '); - sb.append(intent.getComponent().toShortString()); + sb.append(intent.getComponent().flattenToShortString()); sb.append('}'); return stringName = sb.toString(); } diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java index 24c3943..3a5ca66 100644 --- a/services/java/com/android/server/am/IntentBindRecord.java +++ b/services/java/com/android/server/am/IntentBindRecord.java @@ -45,22 +45,30 @@ class IntentBindRecord { /** Set when the service's onUnbind() has asked to be told about new clients. */ boolean doRebind; + String stringName; // caching of toString + void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "service=" + service); - pw.println(prefix + "intent=" + intent.getIntent()); - pw.println(prefix + "binder=" + binder - + " requested=" + requested - + " received=" + received - + " hasBound=" + hasBound - + " doRebind=" + doRebind); + pw.print(prefix); pw.print("service="); pw.println(service); + dumpInService(pw, prefix); + } + + void dumpInService(PrintWriter pw, String prefix) { + pw.print(prefix); pw.print("intent={"); + pw.print(intent.getIntent().toShortString(true, false)); + pw.println('}'); + pw.print(prefix); pw.print("binder="); pw.println(binder); + pw.print(prefix); pw.print("requested="); pw.print(requested); + pw.print(" received="); pw.print(received); + pw.print(" hasBound="); pw.print(hasBound); + pw.print(" doRebind="); pw.println(doRebind); if (apps.size() > 0) { - pw.println(prefix + "Application Bindings:"); Iterator<AppBindRecord> it = apps.values().iterator(); while (it.hasNext()) { AppBindRecord a = it.next(); - pw.println(prefix + "Client " + a.client); - a.dump(pw, prefix + " "); + pw.print(prefix); pw.print("* Client AppBindRecord{"); + pw.print(Integer.toHexString(System.identityHashCode(a))); + pw.print(' '); pw.print(a.client); pw.println('}'); + a.dumpInIntentBind(pw, prefix + " "); } } } @@ -71,9 +79,19 @@ class IntentBindRecord { } public String toString() { - return "IntentBindRecord{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + service.name.toShortString() - + ":" + intent + "}"; + if (stringName != null) { + return stringName; + } + StringBuilder sb = new StringBuilder(128); + sb.append("IntentBindRecord{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(' '); + sb.append(service.shortName); + sb.append(':'); + if (intent != null) { + intent.getIntent().toShortString(sb, false, false); + } + sb.append('}'); + return stringName = sb.toString(); } } diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java index b18aaf7..4381392 100644 --- a/services/java/com/android/server/am/PendingIntentRecord.java +++ b/services/java/com/android/server/am/PendingIntentRecord.java @@ -36,6 +36,8 @@ class PendingIntentRecord extends IIntentSender.Stub { boolean sent = false; boolean canceled = false; + String stringName; + final static class Key { final int type; final String packageName; @@ -142,7 +144,7 @@ class PendingIntentRecord extends IIntentSender.Stub { public String toString() { return "Key{" + typeName() + " pkg=" + packageName - + " intent=" + requestIntent + " flags=0x" + + " intent=" + requestIntent.toShortString(true, false) + " flags=0x" + Integer.toHexString(flags) + "}"; } @@ -260,19 +262,38 @@ class PendingIntentRecord extends IIntentSender.Stub { } void dump(PrintWriter pw, String prefix) { - pw.println(prefix + "packageName=" + key.packageName - + " type=" + key.typeName() - + " flags=0x" + Integer.toHexString(key.flags)); - pw.println(prefix + "activity=" + key.activity + " who=" + key.who); - pw.println(prefix + "requestCode=" + key.requestCode - + " requestResolvedType=" + key.requestResolvedType); - pw.println(prefix + "requestIntent=" + key.requestIntent); - pw.println(prefix + "sent=" + sent + " canceled=" + canceled); + pw.print(prefix); pw.print("uid="); pw.print(uid); + pw.print(" packageName="); pw.print(key.packageName); + pw.print(" type="); pw.print(key.typeName()); + pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags)); + if (key.activity != null || key.who != null) { + pw.print(prefix); pw.print("activity="); pw.print(key.activity); + pw.print(" who="); pw.println(key.who); + } + if (key.requestCode != 0 || key.requestResolvedType != null) { + pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode); + pw.print(" requestResolvedType="); pw.println(key.requestResolvedType); + } + pw.print(prefix); pw.print("requestIntent="); + pw.println(key.requestIntent.toShortString(true, true)); + if (sent || canceled) { + pw.print(prefix); pw.print("sent="); pw.print(sent); + pw.print(" canceled="); pw.println(canceled); + } } public String toString() { - return "IntentSenderRecord{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + key.packageName + " " + key.typeName() + "}"; + if (stringName != null) { + return stringName; + } + StringBuilder sb = new StringBuilder(128); + sb.append("PendingIntentRecord{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(' '); + sb.append(key.packageName); + sb.append(' '); + sb.append(key.typeName()); + sb.append('}'); + return stringName = sb.toString(); } } diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index d2667e7..b76547a 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -106,7 +106,6 @@ class ProcessRecord implements Watchdog.PssRequestor { ActivityManager.ProcessErrorStateInfo notRespondingReport; void dump(PrintWriter pw, String prefix) { - pw.print(prefix); pw.println(this); if (info.className != null) { pw.print(prefix); pw.print("class="); pw.println(info.className); } diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java index b8bf30c..0facefc 100644 --- a/services/java/com/android/server/am/ReceiverList.java +++ b/services/java/com/android/server/am/ReceiverList.java @@ -18,9 +18,12 @@ package com.android.server.am; import android.app.IIntentReceiver; import android.content.Intent; +import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; +import android.util.PrintWriterPrinter; +import android.util.Printer; import java.io.PrintWriter; import java.util.ArrayList; @@ -64,22 +67,26 @@ class ReceiverList extends ArrayList<BroadcastFilter> } void dumpLocal(PrintWriter pw, String prefix) { - pw.println(prefix + "receiver=IBinder " - + Integer.toHexString(System.identityHashCode(receiver.asBinder()))); - pw.println(prefix + "app=" + app + " pid=" + pid + " uid=" + uid); - pw.println(prefix + "curBroadcast=" + curBroadcast - + " linkedToDeath=" + linkedToDeath); + pw.print(prefix); pw.print("app="); pw.print(app); + pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.println(uid); + if (curBroadcast != null || linkedToDeath) { + pw.print(prefix); pw.print("curBroadcast="); pw.print(curBroadcast); + pw.print(" linkedToDeath="); pw.println(linkedToDeath); + } } void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); + Printer pr = new PrintWriterPrinter(pw); dumpLocal(pw, prefix); String p2 = prefix + " "; final int N = size(); for (int i=0; i<N; i++) { BroadcastFilter bf = get(i); - pw.println(prefix + "Filter #" + i + ": " + bf); - bf.dump(pw, p2); + pw.print(prefix); pw.print("Filter #"); pw.print(i); + pw.print(": BroadcastFilter{"); + pw.print(Integer.toHexString(System.identityHashCode(bf))); + pw.println('}'); + bf.dumpInReceiverList(pw, pr, p2); } } @@ -96,7 +103,7 @@ class ReceiverList extends ArrayList<BroadcastFilter> sb.append((app != null ? app.processName : "(unknown name)")); sb.append('/'); sb.append(uid); - sb.append(" client "); + sb.append((receiver.asBinder() instanceof Binder) ? " local:" : " remote:"); sb.append(Integer.toHexString(System.identityHashCode(receiver.asBinder()))); sb.append('}'); return stringName = sb.toString(); diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index a8fc761..fc93b69 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -80,40 +80,46 @@ class ServiceRecord extends Binder { String stringName; // caching of toString void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "intent=" + intent.getIntent()); - pw.println(prefix + "packageName=" + packageName); - pw.println(prefix + "processName=" + processName); - pw.println(prefix + "permission=" + permission); - pw.println(prefix + "baseDir=" + baseDir+ " resDir=" + resDir + " dataDir=" + dataDir); - pw.println(prefix + "app=" + app); - pw.println(prefix + "isForeground=" + isForeground - + " lastActivity=" + lastActivity); - pw.println(prefix + "startRequested=" + startRequested - + " startId=" + lastStartId - + " executeNesting=" + executeNesting - + " executingStart=" + executingStart - + " crashCount=" + crashCount); - pw.println(prefix + "totalRestartCount=" + totalRestartCount - + " restartCount=" + restartCount - + " restartDelay=" + restartDelay - + " restartTime=" + restartTime - + " nextRestartTime=" + nextRestartTime); + pw.print(prefix); pw.print("intent={"); + pw.print(intent.getIntent().toShortString(true, false)); + pw.println('}'); + pw.print(prefix); pw.print("packageName="); pw.println(packageName); + pw.print(prefix); pw.print("processName="); pw.println(processName); + if (permission != null) { + pw.print(prefix); pw.print("permission="); pw.println(permission); + } + pw.print(prefix); pw.print("baseDir="); pw.print(baseDir); + if (!resDir.equals(baseDir)) pw.print(" resDir="); pw.print(resDir); + pw.print(" dataDir="); pw.println(dataDir); + pw.print(prefix); pw.print("app="); pw.println(app); + pw.print(prefix); pw.print("isForeground="); pw.print(isForeground); + pw.print(" lastActivity="); pw.println(lastActivity); + pw.print(prefix); pw.print("startRequested="); pw.print(startRequested); + pw.print(" startId="); pw.print(lastStartId); + pw.print(" executeNesting="); pw.print(executeNesting); + pw.print(" executingStart="); pw.print(executingStart); + pw.print(" crashCount="); pw.println(crashCount); + pw.print(prefix); pw.print("totalRestartCount="); pw.print(totalRestartCount); + pw.print(" restartCount="); pw.print(restartCount); + pw.print(" restartDelay="); pw.print(restartDelay); + pw.print(" restartTime="); pw.print(restartTime); + pw.print(" nextRestartTime="); pw.println(nextRestartTime); if (bindings.size() > 0) { - pw.println(prefix + "Bindings:"); Iterator<IntentBindRecord> it = bindings.values().iterator(); while (it.hasNext()) { IntentBindRecord b = it.next(); - pw.println(prefix + "Binding " + b); - b.dump(pw, prefix + " "); + pw.print(prefix); pw.print("* IntentBindRecord{"); + pw.print(Integer.toHexString(System.identityHashCode(b))); + pw.println("}:"); + b.dumpInService(pw, prefix + " "); } } if (connections.size() > 0) { - pw.println(prefix + "All Connections:"); + pw.print(prefix); pw.println("All Connections:"); Iterator<ConnectionRecord> it = connections.values().iterator(); while (it.hasNext()) { ConnectionRecord c = it.next(); - pw.println(prefix + " " + c); + pw.print(prefix); pw.print(" "); pw.println(c); } } } @@ -165,11 +171,9 @@ class ServiceRecord extends Binder { return stringName; } StringBuilder sb = new StringBuilder(128); - sb.append("ServiceRecord{"); - sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(' '); - sb.append(shortName); - sb.append('}'); + sb.append("ServiceRecord{") + .append(Integer.toHexString(System.identityHashCode(this))) + .append(' ').append(shortName).append('}'); return stringName = sb.toString(); } } diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index aab3736..bcb8f54 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -36,6 +36,8 @@ class TaskRecord { boolean rootWasReset; // True if the intent at the root of the task had // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag. + String stringName; // caching of toString() result. + TaskRecord(int _taskId, ActivityInfo info, Intent _intent, boolean _clearOnBackground) { taskId = _taskId; @@ -53,6 +55,8 @@ class TaskRecord { } void setIntent(Intent _intent, ActivityInfo info) { + stringName = null; + if (info.targetActivity == null) { intent = _intent; realActivity = _intent != null ? _intent.getComponent() : null; @@ -82,23 +86,63 @@ class TaskRecord { } void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "clearOnBackground=" + clearOnBackground - + " numActivities=" + numActivities - + " rootWasReset=" + rootWasReset); - pw.println(prefix + "affinity=" + affinity); - pw.println(prefix + "intent=" + intent); - pw.println(prefix + "affinityIntent=" + affinityIntent); - pw.println(prefix + "origActivity=" + origActivity); - pw.println(prefix + "lastActiveTime=" + lastActiveTime - +" (inactive for " + (getInactiveDuration()/1000) + "s)"); + if (clearOnBackground || numActivities != 0 || rootWasReset) { + pw.print(prefix); pw.print("clearOnBackground="); pw.print(clearOnBackground); + pw.print(" numActivities="); pw.print(numActivities); + pw.print(" rootWasReset="); pw.println(rootWasReset); + } + if (affinity != null) { + pw.print(prefix); pw.print("affinity="); pw.println(affinity); + } + if (intent != null) { + StringBuilder sb = new StringBuilder(128); + sb.append(prefix); sb.append("intent={"); + intent.toShortString(sb, true, false); + sb.append('}'); + pw.println(sb.toString()); + } + if (affinityIntent != null) { + StringBuilder sb = new StringBuilder(128); + sb.append(prefix); sb.append("affinityIntent={"); + affinityIntent.toShortString(sb, true, false); + sb.append('}'); + pw.println(sb.toString()); + } + if (origActivity != null) { + pw.print(prefix); pw.print("origActivity="); + pw.println(origActivity.flattenToShortString()); + } + if (realActivity != null) { + pw.print(prefix); pw.print("realActivity="); + pw.println(realActivity.flattenToShortString()); + } + pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime); + pw.print(" (inactive for "); + pw.print((getInactiveDuration()/1000)); pw.println("s)"); } public String toString() { - return "Task{" + taskId + " " - + (affinity != null ? affinity - : (intent != null ? intent.getComponent().flattenToShortString() - : affinityIntent != null ? affinityIntent.getComponent().flattenToShortString() : "??")) - + "}"; + if (stringName != null) { + return stringName; + } + StringBuilder sb = new StringBuilder(128); + sb.append("TaskRecord{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(" #"); + sb.append(taskId); + if (affinity != null) { + sb.append(" A "); + sb.append(affinity); + } else if (intent != null) { + sb.append(" I "); + sb.append(intent.getComponent().flattenToShortString()); + } else if (affinityIntent != null) { + sb.append(" aI "); + sb.append(affinityIntent.getComponent().flattenToShortString()); + } else { + sb.append(" ??"); + } + sb.append('}'); + return stringName = sb.toString(); } } diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java index fb7a745..ffa8a2a 100644 --- a/services/java/com/android/server/am/UriPermission.java +++ b/services/java/com/android/server/am/UriPermission.java @@ -30,6 +30,8 @@ class UriPermission { final HashSet<HistoryRecord> readActivities = new HashSet<HistoryRecord>(); final HashSet<HistoryRecord> writeActivities = new HashSet<HistoryRecord>(); + String stringName; + UriPermission(int _uid, Uri _uri) { uid = _uid; uri = _uri; @@ -65,18 +67,29 @@ class UriPermission { } public String toString() { - return "UriPermission{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + uri + "}"; + if (stringName != null) { + return stringName; + } + StringBuilder sb = new StringBuilder(128); + sb.append("UriPermission{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(' '); + sb.append(uri); + sb.append('}'); + return stringName = sb.toString(); } void dump(PrintWriter pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + " modeFlags=0x" + Integer.toHexString(modeFlags) - + " uid=" + uid - + " globalModeFlags=0x" - + Integer.toHexString(globalModeFlags)); - pw.println(prefix + " readActivities=" + readActivities); - pw.println(prefix + " writeActivities=" + writeActivities); + pw.print(prefix); pw.print("modeFlags=0x"); + pw.print(Integer.toHexString(modeFlags)); + pw.print(" uid="); pw.print(uid); + pw.print(" globalModeFlags=0x"); + pw.println(Integer.toHexString(globalModeFlags)); + if (readActivities.size() != 0) { + pw.print(prefix); pw.print("readActivities="); pw.println(readActivities); + } + if (writeActivities.size() != 0) { + pw.print(prefix); pw.print("writeActivities="); pw.println(writeActivities); + } } } diff --git a/telephony/java/com/android/internal/telephony/DriverCall.java b/telephony/java/com/android/internal/telephony/DriverCall.java index 6c4e71f..0d9a60f 100644 --- a/telephony/java/com/android/internal/telephony/DriverCall.java +++ b/telephony/java/com/android/internal/telephony/DriverCall.java @@ -44,8 +44,11 @@ public class DriverCall implements Comparable { public String number; public int TOA; public boolean isVoice; + public boolean isVoicePrivacy; public int als; public int numberPresentation; + public String name; + public int namePresentation; /** returns null on error */ static DriverCall @@ -101,11 +104,15 @@ public class DriverCall implements Comparable { public String toString() { return "id=" + index + "," - + (isMT ? "mt" : "mo") + "," + state + "," - + (isVoice ? "voice" : "no_voc") + "," + + "toa=" + TOA + "," + (isMpty ? "conf" : "norm") + "," - + TOA + "," + als + ",cli " + numberPresentation; + + (isMT ? "mt" : "mo") + "," + + als + "," + + (isVoice ? "voc" : "nonvoc") + "," + + (isVoicePrivacy ? "evp" : "noevp") + "," + /*+ "number=" + number */ + ",cli=" + numberPresentation + "," + /*+ "name="+ name */ + "," + namePresentation; } public static State diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java index 59ce5bb..014fbb6 100644 --- a/telephony/java/com/android/internal/telephony/IccConstants.java +++ b/telephony/java/com/android/internal/telephony/IccConstants.java @@ -21,39 +21,44 @@ package com.android.internal.telephony; */ public interface IccConstants { // GSM SIM file ids from TS 51.011 - public static final int EF_ADN = 0x6F3A; - public static final int EF_FDN = 0x6F3B; - public static final int EF_SDN = 0x6F49; - public static final int EF_EXT1 = 0x6F4A; - public static final int EF_EXT2 = 0x6F4B; - public static final int EF_EXT3 = 0x6F4C; - public static final int EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN] - public static final int EF_MWIS = 0x6FCA; - public static final int EF_MBDN = 0x6fc7; - public static final int EF_PNN = 0x6fc5; - public static final int EF_SPN = 0x6F46; - public static final int EF_SMS = 0x6F3C; - public static final int EF_ICCID = 0x2fe2; - public static final int EF_AD = 0x6FAD; - public static final int EF_MBI = 0x6fc9; - public static final int EF_MSISDN = 0x6f40; - public static final int EF_SPDI = 0x6fcd; - public static final int EF_SST = 0x6f38; - public static final int EF_CFIS = 0x6FCB; - public static final int EF_IMG = 0x4f20; + static final int EF_ADN = 0x6F3A; + static final int EF_FDN = 0x6F3B; + static final int EF_SDN = 0x6F49; + static final int EF_EXT1 = 0x6F4A; + static final int EF_EXT2 = 0x6F4B; + static final int EF_EXT3 = 0x6F4C; + static final int EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN] + static final int EF_MWIS = 0x6FCA; + static final int EF_MBDN = 0x6fc7; + static final int EF_PNN = 0x6fc5; + static final int EF_SPN = 0x6F46; + static final int EF_SMS = 0x6F3C; + static final int EF_ICCID = 0x2fe2; + static final int EF_AD = 0x6FAD; + static final int EF_MBI = 0x6fc9; + static final int EF_MSISDN = 0x6f40; + static final int EF_SPDI = 0x6fcd; + static final int EF_SST = 0x6f38; + static final int EF_CFIS = 0x6FCB; + static final int EF_IMG = 0x4f20; // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6 - public static final int EF_MAILBOX_CPHS = 0x6F17; - public static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11; - public static final int EF_CFF_CPHS = 0x6F13; - public static final int EF_SPN_CPHS = 0x6f14; - public static final int EF_SPN_SHORT_CPHS = 0x6f18; - public static final int EF_INFO_CPHS = 0x6f16; + static final int EF_MAILBOX_CPHS = 0x6F17; + static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11; + static final int EF_CFF_CPHS = 0x6F13; + static final int EF_SPN_CPHS = 0x6f14; + static final int EF_SPN_SHORT_CPHS = 0x6f18; + static final int EF_INFO_CPHS = 0x6f16; // CDMA RUIM file ids from 3GPP2 C.S0023-0 - public static final int EF_CST = 0x6f32; - public static final int EF_RUIM_SPN =0x6F41; + static final int EF_CST = 0x6f32; + static final int EF_RUIM_SPN =0x6F41; // SMS record length from TS 51.011 10.5.3 static public final int SMS_RECORD_LENGTH = 176; + + static final String MF_SIM = "3F00"; + static final String DF_TELECOM = "7F10"; + static final String DF_GRAPHICS = "5F50"; + static final String DF_GSM = "7F20"; } diff --git a/telephony/java/com/android/internal/telephony/IccFileHandler.java b/telephony/java/com/android/internal/telephony/IccFileHandler.java index e751c5e..92ddd2c 100644 --- a/telephony/java/com/android/internal/telephony/IccFileHandler.java +++ b/telephony/java/com/android/internal/telephony/IccFileHandler.java @@ -23,7 +23,7 @@ import java.util.ArrayList; /** * {@hide} */ -public abstract class IccFileHandler extends Handler { +public abstract class IccFileHandler extends Handler implements IccConstants { //from TS 11.11 9.1 or elsewhere static protected final int COMMAND_READ_BINARY = 0xb0; @@ -145,7 +145,7 @@ public abstract class IccFileHandler extends Handler { = obtainMessage(EVENT_GET_RECORD_SIZE_DONE, new LoadLinearFixedContext(fileid, recordNum, onLoaded)); - phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, null, + phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid), 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response); } @@ -163,6 +163,7 @@ public abstract class IccFileHandler extends Handler { new LoadLinearFixedContext(IccConstants.EF_IMG, recordNum, onLoaded)); + // TODO(): Verify when path changes are done. phone.mCM.iccIO(COMMAND_GET_RESPONSE, IccConstants.EF_IMG, "img", recordNum, READ_RECORD_MODE_ABSOLUTE, GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null, response); @@ -181,7 +182,7 @@ public abstract class IccFileHandler extends Handler { Message response = obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE, new LoadLinearFixedContext(fileid, onLoaded)); - phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, null, + phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid), 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response); } @@ -198,7 +199,7 @@ public abstract class IccFileHandler extends Handler { Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE, new LoadLinearFixedContext(fileid,onLoaded)); - phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, null, + phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid), 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response); } @@ -216,7 +217,7 @@ public abstract class IccFileHandler extends Handler { Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE, fileid, 0, onLoaded); - phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, null, + phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid), 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response); } @@ -250,7 +251,7 @@ public abstract class IccFileHandler extends Handler { */ public void updateEFLinearFixed(int fileid, int recordNum, byte[] data, String pin2, Message onComplete) { - phone.mCM.iccIO(COMMAND_UPDATE_RECORD, fileid, null, + phone.mCM.iccIO(COMMAND_UPDATE_RECORD, fileid, getEFPath(fileid), recordNum, READ_RECORD_MODE_ABSOLUTE, data.length, IccUtils.bytesToHexString(data), pin2, onComplete); } @@ -261,7 +262,7 @@ public abstract class IccFileHandler extends Handler { * @param data must be exactly as long as the EF */ public void updateEFTransparent(int fileid, byte[] data, Message onComplete) { - phone.mCM.iccIO(COMMAND_UPDATE_BINARY, fileid, null, + phone.mCM.iccIO(COMMAND_UPDATE_BINARY, fileid, getEFPath(fileid), 0, 0, data.length, IccUtils.bytesToHexString(data), null, onComplete); } @@ -394,7 +395,7 @@ public abstract class IccFileHandler extends Handler { lc.results = new ArrayList<byte[]>(lc.countRecords); } - phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, null, + phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid), lc.recordNum, READ_RECORD_MODE_ABSOLUTE, lc.recordSize, null, null, @@ -432,7 +433,7 @@ public abstract class IccFileHandler extends Handler { size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8) + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff); - phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, null, + phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, getEFPath(fileid), 0, 0, size, null, null, obtainMessage(EVENT_READ_BINARY_DONE, fileid, 0, response)); @@ -467,7 +468,7 @@ public abstract class IccFileHandler extends Handler { if (lc.recordNum > lc.countRecords) { sendResult(response, lc.results, null); } else { - phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, null, + phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid), lc.recordNum, READ_RECORD_MODE_ABSOLUTE, lc.recordSize, null, null, @@ -506,6 +507,36 @@ public abstract class IccFileHandler extends Handler { } } + /** + * Returns the root path of the EF file. + * i.e returns MasterFile + DFfile as a string. + * Ex: For EF_ADN on a SIM, it will return "3F007F10" + * This function handles only EFids that are common to + * RUIM, SIM, USIM and other types of Icc cards. + * + * @param efId + * @return root path of the file. + */ + protected String getCommonIccEFPath(int efid) { + switch(efid) { + case EF_ADN: + case EF_FDN: + case EF_MSISDN: + case EF_SDN: + case EF_EXT1: + case EF_EXT2: + case EF_EXT3: + return MF_SIM + DF_TELECOM; + + case EF_ICCID: + return MF_SIM; + case EF_IMG: + return MF_SIM + DF_TELECOM + DF_GRAPHICS; + } + return null; + } + + protected abstract String getEFPath(int efid); protected abstract void logd(String s); protected abstract void loge(String s); diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index 636a223..cebbe5c 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -234,6 +234,11 @@ public final class RIL extends BaseCommands implements CommandsInterface { static final int SOCKET_OPEN_RETRY_MILLIS = 4 * 1000; + // The number of the required config values for broadcast SMS stored in the C struct + // RIL_CDMA_BroadcastServiceInfo + private static final int CDMA_BSI_NO_OF_INTS_STRUCT = 3; + + private static final int CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES = 31; BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { @@ -2017,7 +2022,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: ret = responseInts(p); break; case RIL_REQUEST_CDMA_FLASH: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_BURST_DTMF: ret = responseVoid(p); break; - case RIL_REQUEST_CDMA_SEND_SMS: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_SEND_SMS: ret = responseSMS(p); break; case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: ret = responseVoid(p); break; case RIL_REQUEST_GET_BROADCAST_CONFIG: ret = responseBR_SMS_CNF(p); break; case RIL_REQUEST_SET_BROADCAST_CONFIG: ret = responseVoid(p); break; @@ -2625,8 +2630,16 @@ public final class RIL extends BaseCommands implements CommandsInterface { dc.als = p.readInt(); voiceSettings = p.readInt(); dc.isVoice = (0 == voiceSettings) ? false : true; + + //dc.isVoicePrivacy = (0 != p.readInt()); + int voicePrivacy = p.readInt(); + dc.isVoicePrivacy = (0 != voicePrivacy); + dc.number = p.readString(); - dc.numberPresentation = DriverCall.presentationFromCLIP(p.readInt()); + int np = p.readInt(); + dc.numberPresentation = DriverCall.presentationFromCLIP(np); + dc.name = p.readString(); + dc.namePresentation = p.readInt(); // Make sure there's a leading + on addresses with a TOA // of 145 @@ -2664,7 +2677,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { PDPContextState pdp = new PDPContextState(); pdp.cid = p.readInt(); - pdp.active = p.readInt() == 0 ? false : true; + pdp.active = p.readInt(); pdp.type = p.readString(); pdp.apn = p.readString(); pdp.address = p.readString(); @@ -2730,16 +2743,37 @@ public final class RIL extends BaseCommands implements CommandsInterface { private Object responseCDMA_BR_CNF(Parcel p) { - int numInts; + int numServiceCategories; int response[]; - numInts = p.readInt(); - - response = new int[numInts]; - - response[0] = numInts; - for (int i = 1 ; i < numInts; i++) { - response[i] = p.readInt(); + numServiceCategories = p.readInt(); + + if (numServiceCategories == 0) { + int numInts; + numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1; + response = new int[numInts]; + + // indicate that a zero length table was received + response[0] = 0; + //for all supported service categories set 'english' as default language + //and selection status to false + for (int i = 1, j = 1 + ; i <= (CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES + * CDMA_BSI_NO_OF_INTS_STRUCT) + ; i += CDMA_BSI_NO_OF_INTS_STRUCT, j++ ) { + response[i] = j; + response[i+1] = 1; + response[i+2] = 0; + } + } else { + int numInts; + numInts = numServiceCategories * CDMA_BSI_NO_OF_INTS_STRUCT + 1; + response = new int[numInts]; + + response[0] = numServiceCategories; + for (int i = 1 ; i < numInts; i++) { + response[i] = p.readInt(); + } } return response; @@ -3028,10 +3062,13 @@ public final class RIL extends BaseCommands implements CommandsInterface { public void setCdmaBroadcastConfig(int[] configValuesArray, Message response) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG, response); - for(int i = 0; i < configValuesArray.length; i++) { + rr.mp.writeInt(configValuesArray[0]); + for(int i = 1; i <= (configValuesArray[0] * 3); i++) { rr.mp.writeInt(configValuesArray[i]); } + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + send(rr); } @@ -3041,6 +3078,8 @@ public final class RIL extends BaseCommands implements CommandsInterface { rr.mp.writeInt(1); rr.mp.writeInt(activate); + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + send(rr); } } diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java index 28a9968..7274e99 100644 --- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java @@ -98,7 +98,7 @@ public abstract class ServiceStateTracker extends Handler { protected static final int EVENT_RESET_PREFERRED_NETWORK_TYPE = 21; protected static final int EVENT_CHECK_REPORT_GPRS = 22; protected static final int EVENT_RESTRICTED_STATE_CHANGED = 23; - + //*****CDMA events: protected static final int EVENT_POLL_STATE_REGISTRATION_CDMA = 24; protected static final int EVENT_POLL_STATE_OPERATOR_CDMA = 25; @@ -112,9 +112,6 @@ public abstract class ServiceStateTracker extends Handler { protected static final int EVENT_SIGNAL_STRENGTH_UPDATE_CDMA = 33; protected static final int EVENT_NV_LOADED = 34; - // Event Log Tags - protected static final int EVENT_LOG_CGREG_FAIL = 50107; - //***** Time Zones protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index e0a84ab..651c505 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -64,7 +64,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private static final String LOG_TAG = "CDMA"; private static final boolean DBG = true; - //***** Instance Variables + private CDMAPhone mCdmaPhone; // Indicates baseband will not auto-attach private boolean noAutoAttach = false; @@ -83,20 +83,19 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private CdmaDataConnection mActiveDataConnection; /** Defined cdma connection profiles */ - private static int EXTERNAL_NETWORK_DEFAULT_ID = 0; - private static int EXTERNAL_NETWORK_NUM_TYPES = 1; + private static final int EXTERNAL_NETWORK_DEFAULT_ID = 0; + private static final int EXTERNAL_NETWORK_NUM_TYPES = 1; private boolean[] dataEnabled = new boolean[EXTERNAL_NETWORK_NUM_TYPES]; - //***** Constants - /** * Pool size of CdmaDataConnection objects. */ private static final int DATA_CONNECTION_POOL_SIZE = 1; private static final int POLL_CONNECTION_MILLIS = 5 * 1000; - private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.cdma-reconnect"; + private static final String INTENT_RECONNECT_ALARM = + "com.android.internal.telephony.cdma-reconnect"; private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason"; // Possibly promoate to base class, the only difference is @@ -146,6 +145,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { CdmaDataConnectionTracker(CDMAPhone p) { super(p); + mCdmaPhone = p; p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null); p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); @@ -187,15 +187,15 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { //Unregister from all events phone.mCM.unregisterForAvailable(this); phone.mCM.unregisterForOffOrNotAvailable(this); - ((CDMAPhone) phone).mRuimRecords.unregisterForRecordsLoaded(this); + mCdmaPhone.mRuimRecords.unregisterForRecordsLoaded(this); phone.mCM.unregisterForNVReady(this); phone.mCM.unregisterForDataStateChanged(this); - ((CDMAPhone) phone).mCT.unregisterForVoiceCallEnded(this); - ((CDMAPhone) phone).mCT.unregisterForVoiceCallStarted(this); - ((CDMAPhone) phone).mSST.unregisterForCdmaDataConnectionAttached(this); - ((CDMAPhone) phone).mSST.unregisterForCdmaDataConnectionDetached(this); - ((CDMAPhone) phone).mSST.unregisterForRoamingOn(this); - ((CDMAPhone) phone).mSST.unregisterForRoamingOff(this); + mCdmaPhone.mCT.unregisterForVoiceCallEnded(this); + mCdmaPhone.mCT.unregisterForVoiceCallStarted(this); + mCdmaPhone.mSST.unregisterForCdmaDataConnectionAttached(this); + mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this); + mCdmaPhone.mSST.unregisterForRoamingOn(this); + mCdmaPhone.mSST.unregisterForRoamingOff(this); phone.getContext().unregisterReceiver(this.mIntentReceiver); destroyAllDataConnectionList(); @@ -277,10 +277,10 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { public boolean isDataConnectionAsDesired() { boolean roaming = phone.getServiceState().getRoaming(); - if ( ((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) || - ((CDMAPhone) phone).mRuimRecords.getRecordsLoaded()) && - ((CDMAPhone) phone).mSST.getCurrentCdmaDataConnectionState() == - ServiceState.STATE_IN_SERVICE && + if (((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) || + mCdmaPhone.mRuimRecords.getRecordsLoaded()) && + (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() == + ServiceState.STATE_IN_SERVICE) && (!roaming || getDataOnRoamingEnabled()) && !mIsWifiConnected ) { return (state == State.CONNECTED); @@ -353,7 +353,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { return true; } - int psState = ((CDMAPhone) phone).mSST.getCurrentCdmaDataConnectionState(); + int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState(); boolean roaming = phone.getServiceState().getRoaming(); if ((state == State.IDLE || state == State.SCANNING) @@ -361,9 +361,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { psState == ServiceState.RADIO_TECHNOLOGY_EVDO_0 || psState == ServiceState.RADIO_TECHNOLOGY_EVDO_A) && ((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) || - ((CDMAPhone) phone).mRuimRecords.getRecordsLoaded()) - && (((CDMAPhone) phone).mSST.isConcurrentVoiceAndData() || - phone.getState() == Phone.State.IDLE ) + mCdmaPhone.mRuimRecords.getRecordsLoaded()) + && (mCdmaPhone.mSST.isConcurrentVoiceAndData() || + phone.getState() == Phone.State.IDLE ) && isDataAllowed()) { return setupData(reason); @@ -374,8 +374,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { " dataState=" + state + " PS state=" + psState + " radio state=" + phone.mCM.getRadioState() + - " ruim=" + ((CDMAPhone) phone).mRuimRecords.getRecordsLoaded() + - " concurrentVoice&Data=" + ((CDMAPhone) phone).mSST.isConcurrentVoiceAndData() + + " ruim=" + mCdmaPhone.mRuimRecords.getRecordsLoaded() + + " concurrentVoice&Data=" + mCdmaPhone.mSST.isConcurrentVoiceAndData() + " phoneState=" + phone.getState() + " dataEnabled=" + getAnyDataEnabled() + " roaming=" + roaming + @@ -781,7 +781,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { * @override com.android.internal.telephony.DataConnectionTracker */ protected void onVoiceCallStarted() { - if (state == State.CONNECTED && !((CDMAPhone) phone).mSST.isConcurrentVoiceAndData()) { + if (state == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) { stopNetStatPoll(); phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); } @@ -792,7 +792,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { */ protected void onVoiceCallEnded() { if (state == State.CONNECTED) { - if (!((CDMAPhone) phone).mSST.isConcurrentVoiceAndData()) { + if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) { startNetStatPoll(); phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); } else { @@ -818,7 +818,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { CdmaDataConnection dataConn; for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) { - dataConn = new CdmaDataConnection(((CDMAPhone) phone)); + dataConn = new CdmaDataConnection(mCdmaPhone); dataConnectionList.add(dataConn); } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 6f344b9..d5cad1c 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -485,13 +485,17 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { -1, //[3] baseStationLongitude 0, //[4] cssIndicator; init with 0, because it is treated as a boolean -1, //[5] systemId - -1 //[6] networkId + -1, //[6] networkId + -1, //[7] TSB-58 Roaming indicator // NEWRIL:TODO UNUSED + -1, //[8] Indicates if current system is in PRL // NEWRIL:TODO UNUSED + -1, //[9] Is default roaming indicator from PRL // NEWRIL:TODO UNUSED + -1, //[10] If registration state is 3 this is reason for denial // NEWRIL:TODO UNUSED }; if (states.length > 0) { try { this.mRegistrationState = Integer.parseInt(states[0]); - if (states.length == 10) { + if (states.length >= 10) { for(int i = 0; i < states.length - offset; i++) { if (states[i + offset] != null && states[i + offset].length() > 0) { @@ -536,7 +540,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { case EVENT_POLL_STATE_OPERATOR_CDMA: String opNames[] = (String[])ar.result; - if (opNames != null && opNames.length >= 4) { + if (opNames != null && opNames.length >= 3) { newSS.setOperatorName (opNames[0], opNames[1], opNames[2]); } break; diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java index 7d392f0..9de6c42 100644 --- a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java +++ b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java @@ -17,7 +17,6 @@ package com.android.internal.telephony.cdma; import android.os.*; -import android.os.AsyncResult; import android.util.Log; import com.android.internal.telephony.IccConstants; @@ -68,6 +67,11 @@ public final class RuimFileHandler extends IccFileHandler { super.handleMessage(msg); } + protected String getEFPath(int efid) { + // TODO(): Implement for CDMA EFs. + return getCommonIccEFPath(efid); + } + protected void logd(String msg) { Log.d(LOG_TAG, "[RuimFileHandler] " + msg); } diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java index 13408cf..b18a3f1 100644 --- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java +++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java @@ -53,6 +53,7 @@ public final class RuimRecords extends IccRecords { String mdn = null; // My mobile number String h_sid; String h_nid; + String min2_min1; // 10 digit MIN value MIN2+MIN1 NEWRIL:TODO currently unused // is not initialized @@ -214,6 +215,9 @@ public final class RuimRecords extends IccRecords { mdn = localTemp[0]; h_sid = localTemp[1]; h_nid = localTemp[2]; + if (localTemp.length >= 3) { // NEWRIL:TODO remove when new ril always returns min2_min1 + min2_min1 = localTemp[3]; + } Log.d(LOG_TAG, "MDN: " + mdn); diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 2f26bdc..6428e90 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -135,6 +135,7 @@ public class SmsMessage extends SmsMessageBase { byte[] data; byte count; int countInt; + int addressDigitMode; //currently not supported by the modem-lib: env.mMessageType env.teleService = p.readInt(); //p_cur->uTeleserviceID @@ -153,7 +154,8 @@ public class SmsMessage extends SmsMessageBase { env.serviceCategory = p.readInt(); //p_cur->uServicecategory // address - addr.digitMode = (byte) (0xFF & p.readInt()); //p_cur->sAddress.digit_mode + addressDigitMode = p.readInt(); + addr.digitMode = (byte) (0xFF & addressDigitMode); //p_cur->sAddress.digit_mode addr.numberMode = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_mode addr.ton = p.readInt(); //p_cur->sAddress.number_type addr.numberPlan = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_plan @@ -163,7 +165,13 @@ public class SmsMessage extends SmsMessageBase { //p_cur->sAddress.digits[digitCount] for (int index=0; index < count; index++) { data[index] = p.readByte(); + + // convert the value if it is 4-bit DTMF to 8 bit + if (addressDigitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) { + data[index] = msg.convertDtmfToAscii(data[index]); + } } + addr.origBytes = data; // ignore subaddress @@ -279,6 +287,7 @@ public class SmsMessage extends SmsMessageBase { SubmitPdu ret = new SubmitPdu(); UserData uData = new UserData(); SmsHeader smsHeader; + byte[] data; // Perform null parameter checks. if (message == null || destinationAddress == null) { @@ -287,8 +296,7 @@ public class SmsMessage extends SmsMessageBase { // ** Set UserData + SmsHeader ** try { - // First, try encoding it with the GSM alphabet - int septetCount = GsmAlphabet.countGsmSeptets(message, true); + // First, try encoding it as 7-bit ASCII // User Data (and length) uData.payload = message.getBytes(); @@ -299,9 +307,7 @@ public class SmsMessage extends SmsMessageBase { } // desired TP-Data-Coding-Scheme - uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET; - - // paddingBits not needed for UD_ENCODING_GSM_7BIT_ALPHABET + uData.msgEncoding = UserData.ENCODING_7BIT_ASCII; // sms header if(headerData != null) { @@ -311,7 +317,13 @@ public class SmsMessage extends SmsMessageBase { // no user data header available! } - } catch (EncodeException ex) { + data = sms.getEnvelope(destinationAddress, statusReportRequested, uData, + (headerData != null), (null == headerData)); + + } catch (Exception ex) { + Log.e(LOG_TAG, "getSubmitPdu: 7 bit ASCII encoding in cdma.SMSMesage failed: " + + ex.getMessage()); + Log.w(LOG_TAG, "getSubmitPdu: The message will be sent as UCS-2 encoded message."); byte[] textPart; // Encoding to the 7-bit alphabet failed. Let's see if we can // send it as a UCS-2 encoded message @@ -340,10 +352,10 @@ public class SmsMessage extends SmsMessageBase { } else { // no user data header available! } - } - byte[] data = sms.getEnvelope(destinationAddress, statusReportRequested, uData, + data = sms.getEnvelope(destinationAddress, statusReportRequested, uData, (headerData != null), (null == headerData)); + } if (null == data) return null; @@ -556,6 +568,7 @@ public class SmsMessage extends SmsMessageBase { ByteArrayInputStream bais = new ByteArrayInputStream(pdu); DataInputStream dis = new DataInputStream(new BufferedInputStream(bais)); byte length; + int bearerDataLength; SmsEnvelope env = new SmsEnvelope(); CdmaSmsAddress addr = new CdmaSmsAddress(); @@ -581,9 +594,9 @@ public class SmsMessage extends SmsMessageBase { env.causeCode = dis.readByte(); //encoded BearerData: - length = dis.readByte(); - env.bearerData = new byte[length]; - dis.read(env.bearerData, 0, length); + bearerDataLength = dis.readInt(); + env.bearerData = new byte[bearerDataLength]; + dis.read(env.bearerData, 0, bearerDataLength); dis.close(); } catch (Exception ex) { Log.e(LOG_TAG, "createFromPdu: conversion from byte array to object failed: " + ex); @@ -690,6 +703,7 @@ public class SmsMessage extends SmsMessageBase { switch (encodingType) { case UserData.ENCODING_GSM_7BIT_ALPHABET: + case UserData.ENCODING_7BIT_ASCII: case UserData.ENCODING_UNICODE_16: // user data was already decoded by wmsts-library messageBody = new String(userData); @@ -786,7 +800,7 @@ public class SmsMessage extends SmsMessageBase { // ** SmsEnvelope ** env.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT; - env.teleService = SmsEnvelope.TELESERVICE_WEMT; + env.teleService = SmsEnvelope.TELESERVICE_WMT; env.destAddress = mSmsAddress; env.bearerReply = RETURN_ACK; env.bearerData = encodedBearerData; @@ -874,7 +888,7 @@ public class SmsMessage extends SmsMessageBase { dos.writeByte(env.errorClass); dos.writeByte(env.causeCode); //encoded BearerData: - dos.writeByte(env.bearerData.length); + dos.writeInt(env.bearerData.length); dos.write(env.bearerData, 0, env.bearerData.length); dos.close(); @@ -884,4 +898,37 @@ public class SmsMessage extends SmsMessageBase { } } + /** + * Converts a 4-Bit DTMF encoded symbol from the calling address number to ASCII character + */ + private byte convertDtmfToAscii(byte dtmfDigit) { + byte asciiDigit; + + switch (dtmfDigit) { + case 0: asciiDigit = 68; break; // 'D' + case 1: asciiDigit = 49; break; // '1' + case 2: asciiDigit = 50; break; // '2' + case 3: asciiDigit = 51; break; // '3' + case 4: asciiDigit = 52; break; // '4' + case 5: asciiDigit = 53; break; // '5' + case 6: asciiDigit = 54; break; // '6' + case 7: asciiDigit = 55; break; // '7' + case 8: asciiDigit = 56; break; // '8' + case 9: asciiDigit = 57; break; // '9' + case 10: asciiDigit = 48; break; // '0' + case 11: asciiDigit = 42; break; // '*' + case 12: asciiDigit = 35; break; // '#' + case 13: asciiDigit = 65; break; // 'A' + case 14: asciiDigit = 66; break; // 'B' + case 15: asciiDigit = 67; break; // 'C' + default: + asciiDigit = 32; // Invalid DTMF code + break; + } + + return asciiDigit; + } + + + } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index b889704..9e6ebc4 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -790,7 +790,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private boolean pdpStatesHasActiveCID (ArrayList<PDPContextState> states, int cid) { for (int i = 0, s = states.size() ; i < s ; i++) { - if (states.get(i).cid == cid) return states.get(i).active; + if (states.get(i).cid == cid) return (states.get(i).active != 0); } return false; @@ -836,57 +836,38 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return; } + if (state == State.CONNECTED) { + // The way things are supposed to work, the PDP list + // should not contain the CID after it disconnects. + // However, the way things really work, sometimes the PDP + // context is still listed with active = false, which + // makes it hard to distinguish an activating context from + // an activated-and-then deactivated one. + if (!pdpStatesHasCID(pdpStates, cidActive)) { + // It looks like the PDP context has deactivated. + // Tear everything down and try to reconnect. + + Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting"); + + // Add an event log when the network drops PDP + int cid = -1; + GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); + if (loc != null) cid = loc.getCid(); + EventLog.List val = new EventLog.List(cid, + TelephonyManager.getDefault().getNetworkType()); + EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val); - // This is how things are supposed to work: - // The PDP list is supposed to be empty of the CID - // when it disconnects - - if (state == State.CONNECTED - && !pdpStatesHasCID(pdpStates, cidActive)) { - - // It looks like the PDP context has deactivated - // Tear everything down and try to reconnect - - Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting"); - - // Add an event log when the network drops PDP - int cid = -1; - GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); - if (loc != null) cid = loc.getCid(); - - EventLog.List val = new EventLog.List(cid, - TelephonyManager.getDefault().getNetworkType()); - - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val); - - cleanUpConnection(true, null); - - return; - } - - if (true) { - // - // Workaround for issue #655426 - // - - // -------------------------- - - // This is how some things work now: the PDP context is still - // listed with active = false, which makes it hard to - // distinguish an activating context from an activated-and-then - // deactivated one. - // - // Here, we only consider this authoritative if we asked for the - // PDP list. If it was an unsolicited response, we poll again - // to make sure everyone agrees on the initial state - - if (state == State.CONNECTED - && !pdpStatesHasActiveCID(pdpStates, cidActive)) { + cleanUpConnection(true, null); + return; + } else if (!pdpStatesHasActiveCID(pdpStates, cidActive)) { + // Here, we only consider this authoritative if we asked for the + // PDP list. If it was an unsolicited response, we poll again + // to make sure everyone agrees on the initial state. if (!explicitPoll) { // We think it disconnected but aren't sure...poll from our side phone.mCM.getPDPContextList( - this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE)); + this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE)); } else { Log.i(LOG_TAG, "PDP connection has dropped (active=false case). " + " Reconnecting"); @@ -895,10 +876,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { int cid = -1; GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); if (loc != null) cid = loc.getCid(); - EventLog.List val = new EventLog.List(cid, TelephonyManager.getDefault().getNetworkType()); - EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val); cleanUpConnection(true, null); diff --git a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java b/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java index feb78f8..31cdacf 100644 --- a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java +++ b/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java @@ -21,7 +21,7 @@ package com.android.internal.telephony.gsm; */ public class PDPContextState { public int cid; - public boolean active; + public int active; public String type; public String apn; public String address; diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java index ead1327..a08cdde 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java +++ b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java @@ -16,26 +16,19 @@ package com.android.internal.telephony.gsm; -import android.os.*; -import android.os.AsyncResult; +import android.os.Message; import android.util.Log; import com.android.internal.telephony.IccConstants; -import com.android.internal.telephony.IccException; import com.android.internal.telephony.IccFileHandler; -import com.android.internal.telephony.IccFileTypeMismatch; -import com.android.internal.telephony.IccIoResult; -import com.android.internal.telephony.IccUtils; -import com.android.internal.telephony.PhoneProxy; - -import java.util.ArrayList; /** * {@hide} */ -public final class SIMFileHandler extends IccFileHandler { +public final class SIMFileHandler extends IccFileHandler implements IccConstants { static final String LOG_TAG = "GSM"; + //***** Instance Variables //***** Constructor @@ -59,6 +52,37 @@ public final class SIMFileHandler extends IccFileHandler { super.handleMessage(msg); } + protected String getEFPath(int efid) { + // TODO(): Make changes when USIM is supported + // TODO(): DF_GSM can be 7F20 or 7F21 to handle backward compatibility. + // Implement this after discussion with OEMs. + switch(efid) { + case EF_SMS: + return MF_SIM + DF_TELECOM; + + case EF_EXT6: + case EF_MWIS: + case EF_MBI: + case EF_SPN: + case EF_AD: + case EF_MBDN: + case EF_PNN: + case EF_SPDI: + case EF_SST: + case EF_CFIS: + return MF_SIM + DF_GSM; + + case EF_MAILBOX_CPHS: + case EF_VOICE_MAIL_INDICATOR_CPHS: + case EF_CFF_CPHS: + case EF_SPN_CPHS: + case EF_SPN_SHORT_CPHS: + case EF_INFO_CPHS: + return MF_SIM + DF_GSM; + } + return getCommonIccEFPath(efid); + } + protected void logd(String msg) { Log.d(LOG_TAG, "[SIMFileHandler] " + msg); } diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 3e53654..cb09cea 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -832,22 +832,30 @@ public final class SimulatedCommands extends BaseCommands } /** - * response.obj.result is an String[3] - * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2 - * response.obj.result[1] is LAC if registered or NULL if not - * response.obj.result[2] is CID if registered or NULL if not - * valid LAC are 0x0000 - 0xffff - * valid CID are 0x00000000 - 0xffffffff + * response.obj.result is an String[14] + * See ril.h for details * * Please note that registration state 4 ("unknown") is treated * as "out of service" above */ public void getRegistrationState (Message result) { - String ret[] = new String[3]; + String ret[] = new String[14]; ret[0] = "5"; // registered roam ret[1] = null; ret[2] = null; + ret[3] = null; + ret[4] = null; + ret[5] = null; + ret[6] = null; + ret[7] = null; + ret[8] = null; + ret[9] = null; + ret[10] = null; + ret[11] = null; + ret[12] = null; + ret[13] = null; + ret[14] = null; resultSuccess(result, ret); } diff --git a/tests/AndroidTests/res/values-port/configVarying.xml b/tests/AndroidTests/res/values-32dpi/configVarying.xml index 0e1f247..f903f0f 100644 --- a/tests/AndroidTests/res/values-port/configVarying.xml +++ b/tests/AndroidTests/res/values-32dpi/configVarying.xml @@ -15,8 +15,8 @@ --> <resources> - <item type="configVarying" name="simple">simple portrait</item> + <item type="configVarying" name="simple">simple 32dpi</item> <bag type="configVarying" name="bag"> - <item name="testString">bag portrait</item> + <item name="testString">bag 32dpi</item> </bag> </resources> diff --git a/tests/AndroidTests/res/values-320x200/configVarying.xml b/tests/AndroidTests/res/values-640x400/configVarying.xml index ca2a286..30332c0 100644 --- a/tests/AndroidTests/res/values-320x200/configVarying.xml +++ b/tests/AndroidTests/res/values-640x400/configVarying.xml @@ -15,8 +15,8 @@ --> <resources> - <item type="configVarying" name="simple">simple 320x200</item> + <item type="configVarying" name="simple">simple 640x400</item> <bag type="configVarying" name="bag"> - <item name="testString">bag 320x200</item> + <item name="testString">bag 640x400</item> </bag> </resources> diff --git a/tests/AndroidTests/res/values-fr-rFR/configVarying.xml b/tests/AndroidTests/res/values-fr-rFR/configVarying.xml new file mode 100644 index 0000000..5ecac7c --- /dev/null +++ b/tests/AndroidTests/res/values-fr-rFR/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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. +--> + +<resources> + <item type="configVarying" name="simple">simple fr FR</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag fr FR</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-fr/configVarying.xml b/tests/AndroidTests/res/values-fr/configVarying.xml new file mode 100644 index 0000000..8413b5a --- /dev/null +++ b/tests/AndroidTests/res/values-fr/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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. +--> + +<resources> + <item type="configVarying" name="simple">simple fr</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag fr</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-trackball/configVarying.xml b/tests/AndroidTests/res/values-mcc110-xx/configVarying.xml index 0dec300..82e2435 100644 --- a/tests/AndroidTests/res/values-trackball/configVarying.xml +++ b/tests/AndroidTests/res/values-mcc110-xx/configVarying.xml @@ -15,8 +15,8 @@ --> <resources> - <item type="configVarying" name="simple">simple trackball</item> + <item type="configVarying" name="simple">simple mcc110 xx</item> <bag type="configVarying" name="bag"> - <item name="testString">bag trackball</item> + <item name="testString">bag mcc110 xx</item> </bag> </resources> diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-mcc112/configVarying.xml index 674787e..9c05d77 100644 --- a/tests/AndroidTests/res/values-finger/configVarying.xml +++ b/tests/AndroidTests/res/values-mcc112/configVarying.xml @@ -15,8 +15,8 @@ --> <resources> - <item type="configVarying" name="simple">simple finger</item> + <item type="configVarying" name="simple">simple mcc112</item> <bag type="configVarying" name="bag"> - <item name="testString">bag finger</item> + <item name="testString">bag mcc112</item> </bag> </resources> diff --git a/tests/AndroidTests/res/values-mnc220-xx/configVarying.xml b/tests/AndroidTests/res/values-mnc220-xx/configVarying.xml new file mode 100644 index 0000000..fbc7888 --- /dev/null +++ b/tests/AndroidTests/res/values-mnc220-xx/configVarying.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 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. +--> + +<resources> + <item type="configVarying" name="simple">simple mnc220 xx</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag mnc220 xx</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-keyshidden/configVarying.xml b/tests/AndroidTests/res/values-mnc222-32dpi/configVarying.xml index fdffc4d..03bea33 100644 --- a/tests/AndroidTests/res/values-keyshidden/configVarying.xml +++ b/tests/AndroidTests/res/values-mnc222-32dpi/configVarying.xml @@ -15,8 +15,8 @@ --> <resources> - <item type="configVarying" name="simple">simple keyshidden</item> + <item type="configVarying" name="simple">simple mnc222 32dpi</item> <bag type="configVarying" name="bag"> - <item name="testString">bag keyshidden</item> + <item name="testString">bag mnc222 32dpi</item> </bag> </resources> diff --git a/tests/AndroidTests/res/values-qwerty/configVarying.xml b/tests/AndroidTests/res/values-mnc223/configVarying.xml index 939f682..8936cbc 100644 --- a/tests/AndroidTests/res/values-qwerty/configVarying.xml +++ b/tests/AndroidTests/res/values-mnc223/configVarying.xml @@ -15,8 +15,8 @@ --> <resources> - <item type="configVarying" name="simple">simple qwerty</item> + <item type="configVarying" name="simple">simple mnc223</item> <bag type="configVarying" name="bag"> - <item name="testString">bag qwerty</item> + <item name="testString">bag mnc223</item> </bag> </resources> diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java index 09e3b02..f3c1542 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java @@ -23,27 +23,11 @@ import android.app.ISearchManager; import android.app.SearchManager; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ProviderInfo; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.content.res.XmlResourceParser; import android.os.ServiceManager; -import android.server.search.SearchableInfo; -import android.server.search.SearchableInfo.ActionKeyInfo; -import android.test.ActivityInstrumentationTestCase; -import android.test.MoreAsserts; -import android.test.mock.MockContext; -import android.test.mock.MockPackageManager; +import android.test.ActivityInstrumentationTestCase2; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.util.AndroidRuntimeException; -import android.view.KeyEvent; - -import java.util.ArrayList; -import java.util.List; /** * To launch this test from the command line: @@ -52,7 +36,7 @@ import java.util.List; * -e class com.android.unit_tests.SearchManagerTest \ * com.android.unit_tests/android.test.InstrumentationTestRunner */ -public class SearchManagerTest extends ActivityInstrumentationTestCase<LocalActivity> { +public class SearchManagerTest extends ActivityInstrumentationTestCase2<LocalActivity> { // If non-zero, enable a set of tests that start and stop the search manager. // This is currently disabled because it's causing an unwanted jump from the unit test @@ -71,18 +55,6 @@ public class SearchManagerTest extends ActivityInstrumentationTestCase<LocalActi * testSearchManagerInvocations() * FIX - make it work again * stress test with a very long string - * - * SearchableInfo tests - * Mock the context so I can provide very specific input data - * Confirm OK with "zero" searchables - * Confirm "good" metadata read properly - * Confirm "bad" metadata skipped properly - * Confirm ordering of searchables - * Confirm "good" actionkeys - * confirm "bad" actionkeys are rejected - * confirm XML ordering enforced (will fail today - bug in SearchableInfo) - * findActionKey works - * getIcon works * * SearchManager tests * confirm proper identification of "default" activity based on policy, not hardcoded contacts @@ -195,348 +167,6 @@ public class SearchManagerTest extends ActivityInstrumentationTestCase<LocalActi searchManager.stopSearch(); } } - - /** - * The goal of this test is to confirm proper operation of the - * SearchableInfo helper class. - * - * TODO: The metadata source needs to be mocked out because adding - * searchability metadata via this test is causing it to leak into the - * real system. So for now I'm just going to test for existence of the - * GoogleSearch app (which is searchable). - */ - @LargeTest - public void testSearchableGoogleSearch() { - // test basic array & hashmap - SearchableInfo.buildSearchableList(mContext); - - // test linkage from another activity - // TODO inject this via mocking into the package manager. - // TODO for now, just check for searchable GoogleSearch app (this isn't really a unit test) - ComponentName thisActivity = new ComponentName( - "com.android.googlesearch", - "com.android.googlesearch.GoogleSearch"); - - SearchableInfo si = SearchableInfo.getSearchableInfo(mContext, thisActivity); - assertNotNull(si); - assertTrue(si.mSearchable); - assertEquals(thisActivity, si.mSearchActivity); - - Context appContext = si.getActivityContext(mContext); - assertNotNull(appContext); - MoreAsserts.assertNotEqual(appContext, mContext); - assertEquals("Google Search", appContext.getString(si.getHintId())); - assertEquals("Google", appContext.getString(si.getLabelId())); - } - - /** - * Test that non-searchable activities return no searchable info (this would typically - * trigger the use of the default searchable e.g. contacts) - */ - @LargeTest - public void testNonSearchable() { - // test basic array & hashmap - SearchableInfo.buildSearchableList(mContext); - - // confirm that we return null for non-searchy activities - ComponentName nonActivity = new ComponentName( - "com.android.unit_tests", - "com.android.unit_tests.NO_SEARCH_ACTIVITY"); - SearchableInfo si = SearchableInfo.getSearchableInfo(mContext, nonActivity); - assertNull(si); - } - - /** - * This is an attempt to run the searchable info list with a mocked context. Here are some - * things I'd like to test. - * - * Confirm OK with "zero" searchables - * Confirm "good" metadata read properly - * Confirm "bad" metadata skipped properly - * Confirm ordering of searchables - * Confirm "good" actionkeys - * confirm "bad" actionkeys are rejected - * confirm XML ordering enforced (will fail today - bug in SearchableInfo) - * findActionKey works - * getIcon works - */ - @LargeTest - public void testSearchableMocked() { - MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager()); - MyMockContext mockContext = new MyMockContext(mContext, mockPM); - ArrayList<SearchableInfo> searchables; - int count; - - // build item list with real-world source data - mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH); - SearchableInfo.buildSearchableList(mockContext); - // tests with "real" searchables (deprecate, this should be a unit test) - searchables = SearchableInfo.getSearchablesList(); - count = searchables.size(); - assertTrue(count >= 1); // this isn't really a unit test - checkSearchables(searchables); - - // build item list with mocked search data - // this round of tests confirms good operations with "zero" searchables found - // This should return either a null pointer or an empty list - mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO); - SearchableInfo.buildSearchableList(mockContext); - searchables = SearchableInfo.getSearchablesList(); - if (searchables != null) { - count = searchables.size(); - assertTrue(count == 0); - } - } - - /** - * Generic health checker for an array of searchables. - * - * This is designed to pass for any semi-legal searchable, without knowing much about - * the format of the underlying data. It's fairly easy for a non-compliant application - * to provide meta-data that will pass here (e.g. a non-existent suggestions authority). - * - * @param searchables The list of searchables to examine. - */ - private void checkSearchables(ArrayList<SearchableInfo> searchablesList) { - assertNotNull(searchablesList); - int count = searchablesList.size(); - for (int ii = 0; ii < count; ii++) { - SearchableInfo si = searchablesList.get(ii); - assertNotNull(si); - assertTrue(si.mSearchable); - assertTrue(si.getLabelId() != 0); // This must be a useable string - assertNotEmpty(si.mSearchActivity.getClassName()); - assertNotEmpty(si.mSearchActivity.getPackageName()); - if (si.getSuggestAuthority() != null) { - // The suggestion fields are largely optional, so we'll just confirm basic health - assertNotEmpty(si.getSuggestAuthority()); - assertNullOrNotEmpty(si.getSuggestPath()); - assertNullOrNotEmpty(si.getSuggestSelection()); - assertNullOrNotEmpty(si.getSuggestIntentAction()); - assertNullOrNotEmpty(si.getSuggestIntentData()); - } - /* Add a way to get the entire action key list, then explicitly test its elements */ - /* For now, test the most common action key (CALL) */ - ActionKeyInfo ai = si.findActionKey(KeyEvent.KEYCODE_CALL); - if (ai != null) { - assertEquals(ai.mKeyCode, KeyEvent.KEYCODE_CALL); - // one of these three fields must be non-null & non-empty - boolean m1 = (ai.mQueryActionMsg != null) && (ai.mQueryActionMsg.length() > 0); - boolean m2 = (ai.mSuggestActionMsg != null) && (ai.mSuggestActionMsg.length() > 0); - boolean m3 = (ai.mSuggestActionMsgColumn != null) && - (ai.mSuggestActionMsgColumn.length() > 0); - assertTrue(m1 || m2 || m3); - } - - /* - * Find ways to test these: - * - * private int mSearchMode - * private Drawable mIcon - */ - - /* - * Explicitly not tested here: - * - * Can be null, so not much to see: - * public String mSearchHint - * private String mZeroQueryBanner - * - * To be deprecated/removed, so don't bother: - * public boolean mFilterMode - * public boolean mQuickStart - * private boolean mIconResized - * private int mIconResizeWidth - * private int mIconResizeHeight - * - * All of these are "internal" working variables, not part of any contract - * private ActivityInfo mActivityInfo - * private Rect mTempRect - * private String mSuggestProviderPackage - * private String mCacheActivityContext - */ - } - } - - /** - * Combo assert for "string not null and not empty" - */ - private void assertNotEmpty(final String s) { - assertNotNull(s); - MoreAsserts.assertNotEqual(s, ""); - } - - /** - * Combo assert for "string null or (not null and not empty)" - */ - private void assertNullOrNotEmpty(final String s) { - if (s != null) { - MoreAsserts.assertNotEqual(s, ""); - } - } - - /** - * This is a mock for context. Used to perform a true unit test on SearchableInfo. - * - */ - private class MyMockContext extends MockContext { - - protected Context mRealContext; - protected PackageManager mPackageManager; - - /** - * Constructor. - * - * @param realContext Please pass in a real context for some pass-throughs to function. - */ - MyMockContext(Context realContext, PackageManager packageManager) { - mRealContext = realContext; - mPackageManager = packageManager; - } - - /** - * Resources. Pass through for now. - */ - @Override - public Resources getResources() { - return mRealContext.getResources(); - } - - /** - * Package manager. Pass through for now. - */ - @Override - public PackageManager getPackageManager() { - return mPackageManager; - } - - /** - * Package manager. Pass through for now. - */ - @Override - public Context createPackageContext(String packageName, int flags) - throws PackageManager.NameNotFoundException { - return mRealContext.createPackageContext(packageName, flags); - } - } - -/** - * This is a mock for package manager. Used to perform a true unit test on SearchableInfo. - * - */ - private class MyMockPackageManager extends MockPackageManager { - - public final static int SEARCHABLES_PASSTHROUGH = 0; - public final static int SEARCHABLES_MOCK_ZERO = 1; - public final static int SEARCHABLES_MOCK_ONEGOOD = 2; - public final static int SEARCHABLES_MOCK_ONEGOOD_ONEBAD = 3; - - protected PackageManager mRealPackageManager; - protected int mSearchablesMode; - - public MyMockPackageManager(PackageManager realPM) { - mRealPackageManager = realPM; - mSearchablesMode = SEARCHABLES_PASSTHROUGH; - } - - /** - * Set the mode for various tests. - */ - public void setSearchablesMode(int newMode) { - switch (newMode) { - case SEARCHABLES_PASSTHROUGH: - case SEARCHABLES_MOCK_ZERO: - mSearchablesMode = newMode; - break; - - default: - throw new UnsupportedOperationException(); - } - } - - /** - * Find activities that support a given intent. - * - * Retrieve all activities that can be performed for the given intent. - * - * @param intent The desired intent as per resolveActivity(). - * @param flags Additional option flags. The most important is - * MATCH_DEFAULT_ONLY, to limit the resolution to only - * those activities that support the CATEGORY_DEFAULT. - * - * @return A List<ResolveInfo> containing one entry for each matching - * Activity. These are ordered from best to worst match -- that - * is, the first item in the list is what is returned by - * resolveActivity(). If there are no matching activities, an empty - * list is returned. - */ - @Override - public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { - assertNotNull(intent); - assertEquals(intent.getAction(), Intent.ACTION_SEARCH); - switch (mSearchablesMode) { - case SEARCHABLES_PASSTHROUGH: - return mRealPackageManager.queryIntentActivities(intent, flags); - case SEARCHABLES_MOCK_ZERO: - return null; - default: - throw new UnsupportedOperationException(); - } - } - - /** - * Retrieve an XML file from a package. This is a low-level API used to - * retrieve XML meta data. - * - * @param packageName The name of the package that this xml is coming from. - * Can not be null. - * @param resid The resource identifier of the desired xml. Can not be 0. - * @param appInfo Overall information about <var>packageName</var>. This - * may be null, in which case the application information will be retrieved - * for you if needed; if you already have this information around, it can - * be much more efficient to supply it here. - * - * @return Returns an XmlPullParser allowing you to parse out the XML - * data. Returns null if the xml resource could not be found for any - * reason. - */ - @Override - public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) { - assertNotNull(packageName); - MoreAsserts.assertNotEqual(packageName, ""); - MoreAsserts.assertNotEqual(resid, 0); - switch (mSearchablesMode) { - case SEARCHABLES_PASSTHROUGH: - return mRealPackageManager.getXml(packageName, resid, appInfo); - case SEARCHABLES_MOCK_ZERO: - default: - throw new UnsupportedOperationException(); - } - } - - /** - * Find a single content provider by its base path name. - * - * @param name The name of the provider to find. - * @param flags Additional option flags. Currently should always be 0. - * - * @return ContentProviderInfo Information about the provider, if found, - * else null. - */ - @Override - public ProviderInfo resolveContentProvider(String name, int flags) { - assertNotNull(name); - MoreAsserts.assertNotEqual(name, ""); - assertEquals(flags, 0); - switch (mSearchablesMode) { - case SEARCHABLES_PASSTHROUGH: - return mRealPackageManager.resolveContentProvider(name, flags); - case SEARCHABLES_MOCK_ZERO: - default: - throw new UnsupportedOperationException(); - } - } - } } diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java new file mode 100644 index 0000000..c299b10 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2009 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.unit_tests; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.server.search.SearchableInfo; +import android.server.search.Searchables; +import android.server.search.SearchableInfo.ActionKeyInfo; +import android.test.AndroidTestCase; +import android.test.MoreAsserts; +import android.test.mock.MockContext; +import android.test.mock.MockPackageManager; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.KeyEvent; + +import java.util.ArrayList; +import java.util.List; + +/** + * To launch this test from the command line: + * + * adb shell am instrument -w \ + * -e class com.android.unit_tests.SearchablesTest \ + * com.android.unit_tests/android.test.InstrumentationTestRunner + */ +@SmallTest +public class SearchablesTest extends AndroidTestCase { + + /* + * SearchableInfo tests + * Mock the context so I can provide very specific input data + * Confirm OK with "zero" searchables + * Confirm "good" metadata read properly + * Confirm "bad" metadata skipped properly + * Confirm ordering of searchables + * Confirm "good" actionkeys + * confirm "bad" actionkeys are rejected + * confirm XML ordering enforced (will fail today - bug in SearchableInfo) + * findActionKey works + * getIcon works + */ + + /** + * The goal of this test is to confirm proper operation of the + * SearchableInfo helper class. + * + * TODO: The metadata source needs to be mocked out because adding + * searchability metadata via this test is causing it to leak into the + * real system. So for now I'm just going to test for existence of the + * GoogleSearch app (which is searchable). + */ + public void testSearchableGoogleSearch() { + // test basic array & hashmap + Searchables searchables = new Searchables(mContext); + searchables.buildSearchableList(); + + // test linkage from another activity + // TODO inject this via mocking into the package manager. + // TODO for now, just check for searchable GoogleSearch app (this isn't really a unit test) + ComponentName thisActivity = new ComponentName( + "com.android.googlesearch", + "com.android.googlesearch.GoogleSearch"); + + SearchableInfo si = searchables.getSearchableInfo(thisActivity); + assertNotNull(si); + assertTrue(si.mSearchable); + assertEquals(thisActivity, si.mSearchActivity); + + Context appContext = si.getActivityContext(mContext); + assertNotNull(appContext); + MoreAsserts.assertNotEqual(appContext, mContext); + assertEquals("Google Search", appContext.getString(si.getHintId())); + assertEquals("Google", appContext.getString(si.getLabelId())); + } + + /** + * Test that non-searchable activities return no searchable info (this would typically + * trigger the use of the default searchable e.g. contacts) + */ + public void testNonSearchable() { + // test basic array & hashmap + Searchables searchables = new Searchables(mContext); + searchables.buildSearchableList(); + + // confirm that we return null for non-searchy activities + ComponentName nonActivity = new ComponentName( + "com.android.unit_tests", + "com.android.unit_tests.NO_SEARCH_ACTIVITY"); + SearchableInfo si = searchables.getSearchableInfo(nonActivity); + assertNull(si); + } + + /** + * This is an attempt to run the searchable info list with a mocked context. Here are some + * things I'd like to test. + * + * Confirm OK with "zero" searchables + * Confirm "good" metadata read properly + * Confirm "bad" metadata skipped properly + * Confirm ordering of searchables + * Confirm "good" actionkeys + * confirm "bad" actionkeys are rejected + * confirm XML ordering enforced (will fail today - bug in SearchableInfo) + * findActionKey works + * getIcon works + + */ + public void testSearchableMocked() { + MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager()); + MyMockContext mockContext = new MyMockContext(mContext, mockPM); + Searchables searchables; + ArrayList<SearchableInfo> searchablesList; + int count; + + + // build item list with real-world source data + mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH); + searchables = new Searchables(mockContext); + searchables.buildSearchableList(); + // tests with "real" searchables (deprecate, this should be a unit test) + searchablesList = searchables.getSearchablesList(); + count = searchablesList.size(); + assertTrue(count >= 1); // this isn't really a unit test + checkSearchables(searchablesList); + + // build item list with mocked search data + // this round of tests confirms good operations with "zero" searchables found + // This should return either a null pointer or an empty list + mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO); + searchables = new Searchables(mockContext); + searchables.buildSearchableList(); + searchablesList = searchables.getSearchablesList(); + if (searchablesList != null) { + count = searchablesList.size(); + assertTrue(count == 0); + } + } + + /** + * Generic health checker for an array of searchables. + * + * This is designed to pass for any semi-legal searchable, without knowing much about + * the format of the underlying data. It's fairly easy for a non-compliant application + * to provide meta-data that will pass here (e.g. a non-existent suggestions authority). + * + * @param searchables The list of searchables to examine. + */ + private void checkSearchables(ArrayList<SearchableInfo> searchablesList) { + assertNotNull(searchablesList); + int count = searchablesList.size(); + for (int ii = 0; ii < count; ii++) { + SearchableInfo si = searchablesList.get(ii); + assertNotNull(si); + assertTrue(si.mSearchable); + assertTrue(si.getLabelId() != 0); // This must be a useable string + assertNotEmpty(si.mSearchActivity.getClassName()); + assertNotEmpty(si.mSearchActivity.getPackageName()); + if (si.getSuggestAuthority() != null) { + // The suggestion fields are largely optional, so we'll just confirm basic health + assertNotEmpty(si.getSuggestAuthority()); + assertNullOrNotEmpty(si.getSuggestPath()); + assertNullOrNotEmpty(si.getSuggestSelection()); + assertNullOrNotEmpty(si.getSuggestIntentAction()); + assertNullOrNotEmpty(si.getSuggestIntentData()); + } + /* Add a way to get the entire action key list, then explicitly test its elements */ + /* For now, test the most common action key (CALL) */ + ActionKeyInfo ai = si.findActionKey(KeyEvent.KEYCODE_CALL); + if (ai != null) { + assertEquals(ai.mKeyCode, KeyEvent.KEYCODE_CALL); + // one of these three fields must be non-null & non-empty + boolean m1 = (ai.mQueryActionMsg != null) && (ai.mQueryActionMsg.length() > 0); + boolean m2 = (ai.mSuggestActionMsg != null) && (ai.mSuggestActionMsg.length() > 0); + boolean m3 = (ai.mSuggestActionMsgColumn != null) && + (ai.mSuggestActionMsgColumn.length() > 0); + assertTrue(m1 || m2 || m3); + } + + /* + * Find ways to test these: + * + * private int mSearchMode + * private Drawable mIcon + */ + + /* + * Explicitly not tested here: + * + * Can be null, so not much to see: + * public String mSearchHint + * private String mZeroQueryBanner + * + * To be deprecated/removed, so don't bother: + * public boolean mFilterMode + * public boolean mQuickStart + * private boolean mIconResized + * private int mIconResizeWidth + * private int mIconResizeHeight + * + * All of these are "internal" working variables, not part of any contract + * private ActivityInfo mActivityInfo + * private Rect mTempRect + * private String mSuggestProviderPackage + * private String mCacheActivityContext + */ + } + } + + /** + * Combo assert for "string not null and not empty" + */ + private void assertNotEmpty(final String s) { + assertNotNull(s); + MoreAsserts.assertNotEqual(s, ""); + } + + /** + * Combo assert for "string null or (not null and not empty)" + */ + private void assertNullOrNotEmpty(final String s) { + if (s != null) { + MoreAsserts.assertNotEqual(s, ""); + } + } + + /** + * This is a mock for context. Used to perform a true unit test on SearchableInfo. + * + */ + private class MyMockContext extends MockContext { + + protected Context mRealContext; + protected PackageManager mPackageManager; + + /** + * Constructor. + * + * @param realContext Please pass in a real context for some pass-throughs to function. + */ + MyMockContext(Context realContext, PackageManager packageManager) { + mRealContext = realContext; + mPackageManager = packageManager; + } + + /** + * Resources. Pass through for now. + */ + @Override + public Resources getResources() { + return mRealContext.getResources(); + } + + /** + * Package manager. Pass through for now. + */ + @Override + public PackageManager getPackageManager() { + return mPackageManager; + } + + /** + * Package manager. Pass through for now. + */ + @Override + public Context createPackageContext(String packageName, int flags) + throws PackageManager.NameNotFoundException { + return mRealContext.createPackageContext(packageName, flags); + } + } + +/** + * This is a mock for package manager. Used to perform a true unit test on SearchableInfo. + * + */ + private class MyMockPackageManager extends MockPackageManager { + + public final static int SEARCHABLES_PASSTHROUGH = 0; + public final static int SEARCHABLES_MOCK_ZERO = 1; + public final static int SEARCHABLES_MOCK_ONEGOOD = 2; + public final static int SEARCHABLES_MOCK_ONEGOOD_ONEBAD = 3; + + protected PackageManager mRealPackageManager; + protected int mSearchablesMode; + + public MyMockPackageManager(PackageManager realPM) { + mRealPackageManager = realPM; + mSearchablesMode = SEARCHABLES_PASSTHROUGH; + } + + /** + * Set the mode for various tests. + */ + public void setSearchablesMode(int newMode) { + switch (newMode) { + case SEARCHABLES_PASSTHROUGH: + case SEARCHABLES_MOCK_ZERO: + mSearchablesMode = newMode; + break; + + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Find activities that support a given intent. + * + * Retrieve all activities that can be performed for the given intent. + * + * @param intent The desired intent as per resolveActivity(). + * @param flags Additional option flags. The most important is + * MATCH_DEFAULT_ONLY, to limit the resolution to only + * those activities that support the CATEGORY_DEFAULT. + * + * @return A List<ResolveInfo> containing one entry for each matching + * Activity. These are ordered from best to worst match -- that + * is, the first item in the list is what is returned by + * resolveActivity(). If there are no matching activities, an empty + * list is returned. + */ + @Override + public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { + assertNotNull(intent); + assertEquals(intent.getAction(), Intent.ACTION_SEARCH); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.queryIntentActivities(intent, flags); + case SEARCHABLES_MOCK_ZERO: + return null; + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Retrieve an XML file from a package. This is a low-level API used to + * retrieve XML meta data. + * + * @param packageName The name of the package that this xml is coming from. + * Can not be null. + * @param resid The resource identifier of the desired xml. Can not be 0. + * @param appInfo Overall information about <var>packageName</var>. This + * may be null, in which case the application information will be retrieved + * for you if needed; if you already have this information around, it can + * be much more efficient to supply it here. + * + * @return Returns an XmlPullParser allowing you to parse out the XML + * data. Returns null if the xml resource could not be found for any + * reason. + */ + @Override + public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) { + assertNotNull(packageName); + MoreAsserts.assertNotEqual(packageName, ""); + MoreAsserts.assertNotEqual(resid, 0); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.getXml(packageName, resid, appInfo); + case SEARCHABLES_MOCK_ZERO: + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Find a single content provider by its base path name. + * + * @param name The name of the provider to find. + * @param flags Additional option flags. Currently should always be 0. + * + * @return ContentProviderInfo Information about the provider, if found, + * else null. + */ + @Override + public ProviderInfo resolveContentProvider(String name, int flags) { + assertNotNull(name); + MoreAsserts.assertNotEqual(name, ""); + assertEquals(flags, 0); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.resolveContentProvider(name, flags); + case SEARCHABLES_MOCK_ZERO: + default: + throw new UnsupportedOperationException(); + } + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java index 1ea83c3..e6639d3 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java @@ -98,7 +98,7 @@ public class ConfigTest extends AndroidTestCase { mMetrics = new DisplayMetrics(); mMetrics.widthPixels = 200; mMetrics.heightPixels = 320; - mMetrics.density = 120; + mMetrics.density = 1; } void setProperty(properties p, int value) { @@ -131,7 +131,9 @@ public class ConfigTest extends AndroidTestCase { mMetrics.heightPixels = value; break; case DENSITY: - mMetrics.density = value; + // this is the ratio from the standard + + mMetrics.density = (((float)value)/((float)DisplayMetrics.DEFAULT_DENSITY)); break; default: assert(false); @@ -187,18 +189,16 @@ public class ConfigTest extends AndroidTestCase { */ TotalConfig config = new TotalConfig(); Resources res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple default"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag default"}); + checkValue(res, R.configVarying.simple, "simple default"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag default"}); config = new TotalConfig(); config.setProperty(properties.LANGUAGE, "xx"); res = config.getResources(); -// got simple xx 32dpi -// checkValue(res, R.configVarying.simple, "simple xx"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag xx"}); + checkValue(res, R.configVarying.simple, "simple xx"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag xx"}); config = new TotalConfig(); config.setProperty(properties.LANGUAGE, "xx"); @@ -225,155 +225,160 @@ public class ConfigTest extends AndroidTestCase { config = new TotalConfig(); config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_NOTOUCH); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple notouch"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag notouch"}); + checkValue(res, R.configVarying.simple, "simple notouch"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag notouch"}); config = new TotalConfig(); - config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_FINGER); + config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple finger"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag finger"}); + checkValue(res, R.configVarying.simple, "simple stylus"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag stylus"}); config = new TotalConfig(); - config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); + config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_NOKEYS); res = config.getResources(); -// got simple 32dpi stylus -// checkValue(res, R.configVarying.simple, "simple stylus"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag stylus"}); + checkValue(res, R.configVarying.simple, "simple nokeys"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag nokeys"}); config = new TotalConfig(); - config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_NOKEYS); + config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple nokeys"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag nokeys"}); + checkValue(res, R.configVarying.simple, "simple 12key"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 12key"}); config = new TotalConfig(); - config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_QWERTY); + config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple qwerty"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag qwerty"}); + checkValue(res, R.configVarying.simple, "simple keysexposed"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag keysexposed"}); config = new TotalConfig(); - config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_NONAV); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple 12key"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag 12key"}); + checkValue(res, R.configVarying.simple, "simple nonav"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag nonav"}); config = new TotalConfig(); - config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_YES); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple keyshidden"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag keyshidden"}); + checkValue(res, R.configVarying.simple, "simple dpad"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag dpad"}); config = new TotalConfig(); - config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); + config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_WHEEL); res = config.getResources(); -// got simple 32dpi keysexposed -// checkValue(res, R.configVarying.simple, "simple keysexposed"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag keysexposed"}); + checkValue(res, R.configVarying.simple, "simple wheel"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag wheel"}); config = new TotalConfig(); - config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_NONAV); + config.setProperty(properties.HEIGHT, 480); + config.setProperty(properties.WIDTH, 320); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple nonav"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag nonav"}); + checkValue(res, R.configVarying.simple, "simple 480x320"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 480x320"}); config = new TotalConfig(); - config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD); + config.setProperty(properties.DENSITY, 240); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple dpad"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag dpad"}); + checkValue(res, R.configVarying.simple, "simple 240dpi"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 240dpi"}); config = new TotalConfig(); - config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_TRACKBALL); + config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_LANDSCAPE); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple trackball"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag trackball"}); + checkValue(res, R.configVarying.simple, "simple landscape"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag landscape"}); config = new TotalConfig(); - config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_WHEEL); + config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple wheel"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag wheel"}); + checkValue(res, R.configVarying.simple, "simple square"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag square"}); + } + + @MediumTest + public void testDensity() throws Exception { + // have 32, 240 and the default 160 content. + // rule is that closest wins, with down scaling (larger content) + // being twice as nice as upscaling. + // transition at H/2 * (-1 +/- sqrt(1+8L/H)) + // SO, X < 49 goes to 32 + // 49 >= X < 182 goes to 160 + // X >= 182 goes to 240 + TotalConfig config = new TotalConfig(); + config.setProperty(properties.DENSITY, 2); + Resources res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple 32dpi"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 32dpi"}); config = new TotalConfig(); - config.setProperty(properties.HEIGHT, 320); - config.setProperty(properties.WIDTH, 200); + config.setProperty(properties.DENSITY, 32); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple 320x200"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag 320x200"}); + checkValue(res, R.configVarying.simple, "simple 32dpi"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 32dpi"}); config = new TotalConfig(); - config.setProperty(properties.HEIGHT, 480); - config.setProperty(properties.WIDTH, 320); + config.setProperty(properties.DENSITY, 48); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple 480x320"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag 480x320"}); + checkValue(res, R.configVarying.simple, "simple 32dpi"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 32dpi"}); config = new TotalConfig(); - config.setProperty(properties.DENSITY, 240); + config.setProperty(properties.DENSITY, 49); res = config.getResources(); - checkValue(res, R.configVarying.simple, "simple 240dpi"); + checkValue(res, R.configVarying.simple, "simple default"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag 240dpi"}); + R.styleable.TestConfig, new String[]{"bag default"}); config = new TotalConfig(); - config.setProperty(properties.DENSITY, 120); + config.setProperty(properties.DENSITY, 150); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple 120dpi"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag 120dpi"}); + checkValue(res, R.configVarying.simple, "simple default"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag default"}); config = new TotalConfig(); - config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_LANDSCAPE); + config.setProperty(properties.DENSITY, 181); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple landscape"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag landscape"}); + checkValue(res, R.configVarying.simple, "simple default"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag default"}); config = new TotalConfig(); - config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_PORTRAIT); + config.setProperty(properties.DENSITY, 182); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple portrait"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag portrait"}); + checkValue(res, R.configVarying.simple, "simple 240dpi"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 240dpi"}); config = new TotalConfig(); - config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); + config.setProperty(properties.DENSITY, 239); res = config.getResources(); -// got simple square 32dpi -// checkValue(res, R.configVarying.simple, "simple square"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag square"}); + checkValue(res, R.configVarying.simple, "simple 240dpi"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 240dpi"}); + + config = new TotalConfig(); + config.setProperty(properties.DENSITY, 490); + res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple 240dpi"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 240dpi"}); } // TODO - add tests for special cases - ie, other key params seem ignored if @@ -407,10 +412,9 @@ public class ConfigTest extends AndroidTestCase { config = new TotalConfig(); config.setProperty(properties.MNC, 333); res = config.getResources(); -// got simple 24dpi -// checkValue(res, R.configVarying.simple, "simple default"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag default"}); + checkValue(res, R.configVarying.simple, "simple default"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag default"}); } @MediumTest @@ -419,13 +423,31 @@ public class ConfigTest extends AndroidTestCase { * Verify that in cases of ties, the specific ordering is followed */ - /* full A + B + C doesn't exist. Do we get A + C or B + C? + /** + * Precidence order: mcc, mnc, locale, orientation, density, + * touchscreen, hidden, keyboard, navigation, width-height + */ + + /** + * verify mcc trumps mnc. Have 110-xx, 220-xx but no 110-220 + * so with is selected? Should be mcc110-xx. */ TotalConfig config = new TotalConfig(); + config.setProperty(properties.MCC, 110); + config.setProperty(properties.MNC, 220); + config.setProperty(properties.LANGUAGE, "xx"); + Resources res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple mcc110 xx"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag mcc110 xx"}); + + /* full A + B + C doesn't exist. Do we get A + C or B + C? + */ + config = new TotalConfig(); config.setProperty(properties.MCC, 111); config.setProperty(properties.MNC, 222); config.setProperty(properties.LANGUAGE, "xx"); - Resources res = config.getResources(); + res = config.getResources(); checkValue(res, R.configVarying.simple, "simple mcc111 mnc222"); checkValue(res, R.configVarying.bag, R.styleable.TestConfig, new String[]{"bag mcc111 mnc222"}); @@ -433,7 +455,8 @@ public class ConfigTest extends AndroidTestCase { config = new TotalConfig(); config.setProperty(properties.MNC, 222); config.setProperty(properties.LANGUAGE, "xx"); - config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); + config.setProperty(properties.ORIENTATION, + Configuration.ORIENTATION_SQUARE); res = config.getResources(); checkValue(res, R.configVarying.simple, "simple mnc222 xx"); checkValue(res, R.configVarying.bag, @@ -441,60 +464,77 @@ public class ConfigTest extends AndroidTestCase { config = new TotalConfig(); config.setProperty(properties.LANGUAGE, "xx"); - config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); + config.setProperty(properties.ORIENTATION, + Configuration.ORIENTATION_SQUARE); config.setProperty(properties.DENSITY, 32); res = config.getResources(); - checkValue(res, R.configVarying.simple, "simple xx 32dpi"); + checkValue(res, R.configVarying.simple, "simple xx square"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag xx 32dpi"}); + R.styleable.TestConfig, new String[]{"bag xx square"}); config = new TotalConfig(); - config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE); + config.setProperty(properties.ORIENTATION, + Configuration.ORIENTATION_SQUARE); config.setProperty(properties.DENSITY, 32); - config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); + config.setProperty(properties.TOUCHSCREEN, + Configuration.TOUCHSCREEN_STYLUS); res = config.getResources(); - checkValue(res, R.configVarying.simple, "simple 32dpi stylus"); + checkValue(res, R.configVarying.simple, "simple square 32dpi"); checkValue(res, R.configVarying.bag, - R.styleable.TestConfig, new String[]{"bag 32dpi stylus"}); + R.styleable.TestConfig, new String[]{"bag square 32dpi"}); config = new TotalConfig(); config.setProperty(properties.DENSITY, 32); - config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); - config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); + config.setProperty(properties.TOUCHSCREEN, + Configuration.TOUCHSCREEN_STYLUS); + config.setProperty(properties.KEYBOARDHIDDEN, + Configuration.KEYBOARDHIDDEN_NO); res = config.getResources(); checkValue(res, R.configVarying.simple, "simple 32dpi stylus"); checkValue(res, R.configVarying.bag, R.styleable.TestConfig, new String[]{"bag 32dpi stylus"}); config = new TotalConfig(); - config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS); - config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); + config.setProperty(properties.TOUCHSCREEN, + Configuration.TOUCHSCREEN_STYLUS); + config.setProperty(properties.KEYBOARDHIDDEN, + Configuration.KEYBOARDHIDDEN_NO); config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); res = config.getResources(); -// got simple 32dpi stylus -// checkValue(res, R.configVarying.simple, "simple stylus 12key"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag stylus 12key"}); + checkValue(res, R.configVarying.simple, "simple stylus keysexposed"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag stylus keysexposed"}); config = new TotalConfig(); - config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO); + config.setProperty(properties.KEYBOARDHIDDEN, + Configuration.KEYBOARDHIDDEN_NO); config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); - config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD); + config.setProperty(properties.NAVIGATION, + Configuration.NAVIGATION_DPAD); res = config.getResources(); -// got simple 32dpi exposed -// checkValue(res, R.configVarying.simple, "simple stylus keysexposed"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag stylus keysexposed"}); + checkValue(res, R.configVarying.simple, "simple keysexposed 12key"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag keysexposed 12key"}); config = new TotalConfig(); config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY); - config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD); + config.setProperty(properties.NAVIGATION, + Configuration.NAVIGATION_DPAD); config.setProperty(properties.HEIGHT, 63); config.setProperty(properties.WIDTH, 57); res = config.getResources(); -// got simple 240dpi -// checkValue(res, R.configVarying.simple, "simple 12key dpad"); -// checkValue(res, R.configVarying.bag, -// R.styleable.TestConfig, new String[]{"bag 12key dpad"}); + checkValue(res, R.configVarying.simple, "simple 12key dpad"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 12key dpad"}); + + config = new TotalConfig(); + config.setProperty(properties.NAVIGATION, + Configuration.NAVIGATION_DPAD); + config.setProperty(properties.HEIGHT, 640); + config.setProperty(properties.WIDTH, 400); + res = config.getResources(); + checkValue(res, R.configVarying.simple, "simple dpad"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag dpad"}); } } diff --git a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java index 663b7a4..6f89fce 100644 --- a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java +++ b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java @@ -147,4 +147,56 @@ public class AutoCompleteTextViewPopup // now try moving "down" - nothing should happen since there's no longer an adapter sendKeys("DPAD_DOWN"); } + + /** Test the show/hide behavior of the drop-down. */ + @MediumTest + public void testPopupShow() throws Throwable { + AutoCompleteTextViewSimple theActivity = getActivity(); + final AutoCompleteTextView textView = theActivity.getTextView(); + final Instrumentation instrumentation = getInstrumentation(); + + // Drop-down should not be showing when no text has been entered + assertFalse("isPopupShowing() on start", textView.isPopupShowing()); + + // focus and type + textView.requestFocus(); + instrumentation.waitForIdleSync(); + sendKeys("A"); + + // Drop-down should now be visible + assertTrue("isPopupShowing() after typing", textView.isPopupShowing()); + + // Clear the text + runTestOnUiThread(new Runnable() { + public void run() { + textView.setText(""); + } + }); + instrumentation.waitForIdleSync(); + + // Drop-down should be hidden when text is cleared + assertFalse("isPopupShowing() after text cleared", textView.isPopupShowing()); + + // Set the text, without filtering + runTestOnUiThread(new Runnable() { + public void run() { + textView.setText("a", false); + } + }); + instrumentation.waitForIdleSync(); + + // Drop-down should still be hidden + assertFalse("isPopupShowing() after setText(\"a\", false)", textView.isPopupShowing()); + + // Set the text, now with filtering + runTestOnUiThread(new Runnable() { + public void run() { + textView.setText("a"); + } + }); + instrumentation.waitForIdleSync(); + + // Drop-down should show up after setText() with filtering + assertTrue("isPopupShowing() after text set", textView.isPopupShowing()); + } } diff --git a/tools/layoutlib/bridge/.gitignore b/tools/layoutlib/bridge/.gitignore new file mode 100644 index 0000000..efa6632 --- /dev/null +++ b/tools/layoutlib/bridge/.gitignore @@ -0,0 +1 @@ +bin/*
\ No newline at end of file |