diff options
Diffstat (limited to 'core/tests/coretests/src/android/app')
37 files changed, 4731 insertions, 0 deletions
diff --git a/core/tests/coretests/src/android/app/SearchManagerTest.java b/core/tests/coretests/src/android/app/SearchManagerTest.java new file mode 100644 index 0000000..21ed4c5 --- /dev/null +++ b/core/tests/coretests/src/android/app/SearchManagerTest.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2006 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.app.activity.LocalActivity; + +import android.app.Activity; +import android.app.ISearchManager; +import android.app.SearchManager; +import android.app.SearchableInfo; +import android.content.ComponentName; +import android.content.Context; +import android.os.ServiceManager; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; + +/** + * To launch this test from the command line: + * + * adb shell am instrument -w \ + * -e class com.android.unit_tests.SearchManagerTest \ + * com.android.unit_tests/android.test.InstrumentationTestRunner + */ +public class SearchManagerTest extends ActivityInstrumentationTestCase2<LocalActivity> { + + private ComponentName SEARCHABLE_ACTIVITY = + new ComponentName("com.android.frameworks.coretests", + "android.app.activity.SearchableActivity"); + + /* + * Bug list of test ideas. + * + * testSearchManagerInterfaceAvailable() + * Exercise the interface obtained + * + * testSearchManagerAvailable() + * Exercise the interface obtained + * + * testSearchManagerInvocations() + * FIX - make it work again + * stress test with a very long string + * + * SearchManager tests + * confirm proper identification of "default" activity based on policy, not hardcoded contacts + * + * SearchBar tests + * Maybe have to do with framework / unittest runner - need instrumented activity? + * How can we unit test the suggestions content providers? + * Should I write unit tests for any of them? + * Test scenarios: + * type-BACK (cancel) + * type-GO (send) + * type-navigate-click (suggestion) + * type-action + * type-navigate-action (suggestion) + */ + + /** + * Local copy of activity context + */ + Context mContext; + + public SearchManagerTest() { + super("com.android.frameworks.coretests", LocalActivity.class); + } + + /** + * Setup any common data for the upcoming tests. + */ + @Override + public void setUp() throws Exception { + super.setUp(); + + Activity testActivity = getActivity(); + mContext = testActivity; + } + + private ISearchManager getSearchManagerService() { + return ISearchManager.Stub.asInterface( + ServiceManager.getService(Context.SEARCH_SERVICE)); + } + + /** + * The goal of this test is to confirm that we can obtain + * a search manager interface. + */ + @MediumTest + public void testSearchManagerInterfaceAvailable() { + assertNotNull(getSearchManagerService()); + } + + /** + * The goal of this test is to confirm that we can obtain + * a search manager at any time, and that for any given context, + * it is a singleton. + */ + @LargeTest + public void testSearchManagerAvailable() { + SearchManager searchManager1 = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager1); + SearchManager searchManager2 = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager2); + assertSame(searchManager1, searchManager2 ); + } + + @MediumTest + public void testSearchables() { + SearchManager searchManager = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + SearchableInfo si; + + si = searchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, false); + assertNotNull(si); + assertFalse(searchManager.isDefaultSearchable(si)); + si = searchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, true); + assertNotNull(si); + assertTrue(searchManager.isDefaultSearchable(si)); + si = searchManager.getSearchableInfo(null, true); + assertNotNull(si); + assertTrue(searchManager.isDefaultSearchable(si)); + } + + /** + * Tests that startSearch() can be called multiple times without stopSearch() + * in between. + */ + @MediumTest + public void testStartSearchIdempotent() throws Exception { + SearchManager searchManager = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager); + + searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false); + searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false); + searchManager.stopSearch(); + } + + /** + * Tests that stopSearch() can be called when the search UI is not visible and can be + * called multiple times without startSearch() in between. + */ + @MediumTest + public void testStopSearchIdempotent() throws Exception { + SearchManager searchManager = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager); + searchManager.stopSearch(); + + searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false); + searchManager.stopSearch(); + searchManager.stopSearch(); + } + + /** + * The goal of this test is to confirm that we can start and then + * stop a simple search. + */ + @MediumTest + public void testSearchManagerInvocations() throws Exception { + SearchManager searchManager = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager); + + // These tests should simply run to completion w/o exceptions + searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false); + searchManager.stopSearch(); + + searchManager.startSearch("", false, SEARCHABLE_ACTIVITY, null, false); + searchManager.stopSearch(); + + searchManager.startSearch("test search string", false, SEARCHABLE_ACTIVITY, null, false); + searchManager.stopSearch(); + + searchManager.startSearch("test search string", true, SEARCHABLE_ACTIVITY, null, false); + searchManager.stopSearch(); + } + +} diff --git a/core/tests/coretests/src/android/app/SearchablesTest.java b/core/tests/coretests/src/android/app/SearchablesTest.java new file mode 100644 index 0000000..9b4520e --- /dev/null +++ b/core/tests/coretests/src/android/app/SearchablesTest.java @@ -0,0 +1,477 @@ +/* + * 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.app.SearchManager; +import android.app.SearchableInfo; +import android.app.SearchableInfo.ActionKeyInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +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.RemoteException; +import android.server.search.Searchables; +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 + * GlobalSearch app (which is searchable). + */ + public void testSearchableGlobalSearch() { + // 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 GlobalSearch app (this isn't really a unit test) + ComponentName thisActivity = new ComponentName( + "com.android.globalsearch", + "com.android.globalsearch.GlobalSearch"); + + SearchableInfo si = searchables.getSearchableInfo(thisActivity); + assertNotNull(si); + assertEquals(thisActivity, si.getSearchActivity()); + + Context appContext = si.getActivityContext(mContext); + assertNotNull(appContext); + MoreAsserts.assertNotEqual(appContext, mContext); + assertEquals("Quick Search Box", appContext.getString(si.getHintId())); + assertEquals("Quick Search Box", 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.frameworks.coretests", + "com.android.frameworks.coretests.activity.NO_SEARCH_ACTIVITY"); + SearchableInfo si = searchables.getSearchableInfo(nonActivity); + assertNull(si); + } + + /** + * Test that there is a default searchable (aka global search provider). + */ + public void testDefaultSearchable() { + Searchables searchables = new Searchables(mContext); + searchables.buildSearchableList(); + SearchableInfo si = searchables.getDefaultSearchable(); + checkSearchable(si); + assertTrue(searchables.isDefaultSearchable(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 testSearchablesListReal() { + MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager()); + MyMockContext mockContext = new MyMockContext(mContext, mockPM); + + // build item list with real-world source data + mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH); + Searchables searchables = new Searchables(mockContext); + searchables.buildSearchableList(); + // tests with "real" searchables (deprecate, this should be a unit test) + ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList(); + int count = searchablesList.size(); + assertTrue(count >= 1); // this isn't really a unit test + checkSearchables(searchablesList); + ArrayList<SearchableInfo> global = searchables.getSearchablesInGlobalSearchList(); + checkSearchables(global); + } + + /** + * This round of tests confirms good operations with "zero" searchables found + */ + public void testSearchablesListEmpty() { + MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager()); + MyMockContext mockContext = new MyMockContext(mContext, mockPM); + + mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO); + Searchables searchables = new Searchables(mockContext); + searchables.buildSearchableList(); + ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList(); + assertNotNull(searchablesList); + MoreAsserts.assertEmpty(searchablesList); + ArrayList<SearchableInfo> global = searchables.getSearchablesInGlobalSearchList(); + MoreAsserts.assertEmpty(global); + } + + /** + * 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); + checkSearchable(si); + } + } + + private void checkSearchable(SearchableInfo si) { + assertNotNull(si); + assertTrue(si.getLabelId() != 0); // This must be a useable string + assertNotEmpty(si.getSearchActivity().getClassName()); + assertNotEmpty(si.getSearchActivity().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.getKeyCode(), KeyEvent.KEYCODE_CALL); + // one of these three fields must be non-null & non-empty + boolean m1 = (ai.getQueryActionMsg() != null) && (ai.getQueryActionMsg().length() > 0); + boolean m2 = (ai.getSuggestActionMsg() != null) && (ai.getSuggestActionMsg().length() > 0); + boolean m3 = (ai.getSuggestActionMsgColumn() != null) && + (ai.getSuggestActionMsgColumn().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); + } + + /** + * Message broadcast. Pass through for now. + */ + @Override + public void sendBroadcast(Intent intent) { + mRealContext.sendBroadcast(intent); + } + } + +/** + * 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); + assertTrue(intent.getAction().equals(Intent.ACTION_SEARCH) + || intent.getAction().equals(Intent.ACTION_WEB_SEARCH)); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.queryIntentActivities(intent, flags); + case SEARCHABLES_MOCK_ZERO: + return null; + default: + throw new UnsupportedOperationException(); + } + } + + @Override + public ResolveInfo resolveActivity(Intent intent, int flags) { + assertNotNull(intent); + assertTrue(intent.getAction().equals(Intent.ACTION_WEB_SEARCH) + || intent.getAction().equals(SearchManager.INTENT_ACTION_GLOBAL_SEARCH)); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.resolveActivity(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(); + } + } + + /** + * Get the activity information for a particular activity. + * + * @param name The name of the activity to find. + * @param flags Additional option flags. + * + * @return ActivityInfo Information about the activity, if found, else null. + */ + @Override + public ActivityInfo getActivityInfo(ComponentName name, int flags) + throws NameNotFoundException { + assertNotNull(name); + MoreAsserts.assertNotEqual(name, ""); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.getActivityInfo(name, flags); + case SEARCHABLES_MOCK_ZERO: + throw new NameNotFoundException(); + default: + throw new UnsupportedOperationException(); + } + } + } +} + diff --git a/core/tests/coretests/src/android/app/SuggestionProvider.java b/core/tests/coretests/src/android/app/SuggestionProvider.java new file mode 100644 index 0000000..9fb7dcf --- /dev/null +++ b/core/tests/coretests/src/android/app/SuggestionProvider.java @@ -0,0 +1,110 @@ +/* + * 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.app.SearchManager; +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.Intent; +import android.content.UriMatcher; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.net.Uri; + +/** Simple test provider that runs in the local process. + * + * Used by {@link SearchManagerTest}. + */ +public class SuggestionProvider extends ContentProvider { + private static final String TAG = "SuggestionProvider"; + + private static final int SEARCH_SUGGESTIONS = 1; + + private static final UriMatcher sURLMatcher = new UriMatcher( + UriMatcher.NO_MATCH); + + static { + sURLMatcher.addURI("*", SearchManager.SUGGEST_URI_PATH_QUERY, + SEARCH_SUGGESTIONS); + sURLMatcher.addURI("*", SearchManager.SUGGEST_URI_PATH_QUERY + "/*", + SEARCH_SUGGESTIONS); + } + + private static final String[] COLUMNS = new String[] { + "_id", + SearchManager.SUGGEST_COLUMN_TEXT_1, + SearchManager.SUGGEST_COLUMN_INTENT_ACTION, + SearchManager.SUGGEST_COLUMN_QUERY + }; + + public SuggestionProvider() { + } + + @Override + public boolean onCreate() { + return true; + } + + @Override + public Cursor query(Uri url, String[] projectionIn, String selection, + String[] selectionArgs, String sort) { + int match = sURLMatcher.match(url); + switch (match) { + case SEARCH_SUGGESTIONS: + String query = url.getLastPathSegment(); + MatrixCursor cursor = new MatrixCursor(COLUMNS); + String[] suffixes = { "", "a", " foo", "XXXXXXXXXXXXXXXXX" }; + for (String suffix : suffixes) { + addRow(cursor, query + suffix); + } + return cursor; + default: + throw new IllegalArgumentException("Unknown URL: " + url); + } + } + + private void addRow(MatrixCursor cursor, String string) { + long id = cursor.getCount(); + cursor.newRow().add(id).add(string).add(Intent.ACTION_SEARCH).add(string); + } + + @Override + public String getType(Uri url) { + int match = sURLMatcher.match(url); + switch (match) { + case SEARCH_SUGGESTIONS: + return SearchManager.SUGGEST_MIME_TYPE; + default: + throw new IllegalArgumentException("Unknown URL: " + url); + } + } + + @Override + public int update(Uri url, ContentValues values, String where, String[] whereArgs) { + throw new UnsupportedOperationException("update not supported"); + } + + @Override + public Uri insert(Uri url, ContentValues initialValues) { + throw new UnsupportedOperationException("insert not supported"); + } + + @Override + public int delete(Uri url, String where, String[] whereArgs) { + throw new UnsupportedOperationException("delete not supported"); + } +} diff --git a/core/tests/coretests/src/android/app/activity/AbortReceiver.java b/core/tests/coretests/src/android/app/activity/AbortReceiver.java new file mode 100644 index 0000000..fef1775 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/AbortReceiver.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package android.app.activity; + +import android.content.Context; +import android.content.Intent; +import android.content.BroadcastReceiver; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; +import android.util.Log; + +public class AbortReceiver extends BroadcastReceiver +{ + public AbortReceiver() + { + } + + public void onReceive(Context context, Intent intent) + { + //Log.i("AbortReceiver", "onReceiveIntent!"); + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(LaunchpadActivity.RECEIVER_ABORT); + caller.transact(LaunchpadActivity.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + + // abort the broadcast!!! + abortBroadcast(); + } +} diff --git a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java new file mode 100644 index 0000000..61d73bc --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2008 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.activity; + +import android.app.ActivityManager; +import android.content.Context; +import android.content.pm.ConfigurationInfo; +import android.content.res.Configuration; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; + +import java.util.Iterator; +import java.util.List; + +public class ActivityManagerTest extends AndroidTestCase { + + protected Context mContext; + protected ActivityManager mActivityManager; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mContext = getContext(); + mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + } + + // TODO should write a test for getRecentTasks() + // TODO should write a test for getRunningTasks() + // TODO should write a test for getMemoryInfo() + + // TODO: Find a way to re-enable this. It fails if any other app has failed during startup. + // This is probably an OK assumption given the desired system status when we run unit tests, + // but it's not necessarily the right assumption for a unit test. + @Suppress + public void disabledTestErrorTasksEmpty() throws Exception { + + List<ActivityManager.ProcessErrorStateInfo> errList; + + errList = mActivityManager.getProcessesInErrorState(); + + // test: confirm list is empty + assertNull(errList); + } + + // TODO: Force an activity into an error state - then see if we can catch it here? + @SmallTest + public void testErrorTasksWithError() throws Exception { + + List<ActivityManager.ProcessErrorStateInfo> errList; + + // TODO force another process into an error condition. How? + + // test: confirm error list length is at least 1 under varying query lengths +// checkErrorListMax(1,-1); + + errList = mActivityManager.getProcessesInErrorState(); + + // test: the list itself is healthy + checkErrorListSanity(errList); + + // test: confirm our application shows up in the list + } + + // TODO: Force an activity into an ANR state - then see if we can catch it here? + @SmallTest + public void testErrorTasksWithANR() throws Exception { + + List<ActivityManager.ProcessErrorStateInfo> errList; + + // TODO: force an application into an ANR state + + errList = mActivityManager.getProcessesInErrorState(); + + // test: the list itself is healthy + checkErrorListSanity(errList); + + // test: confirm our ANR'ing application shows up in the list + } + + @SmallTest + public void testGetDeviceConfigurationInfo() throws Exception { + ConfigurationInfo config = mActivityManager.getDeviceConfigurationInfo(); + assertNotNull(config); + // Validate values against configuration retrieved from resources + Configuration vconfig = mContext.getResources().getConfiguration(); + assertNotNull(vconfig); + assertEquals(config.reqKeyboardType, vconfig.keyboard); + assertEquals(config.reqTouchScreen, vconfig.touchscreen); + assertEquals(config.reqNavigation, vconfig.navigation); + if (vconfig.navigation == Configuration.NAVIGATION_NONAV) { + assertNotNull(config.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV); + } + if (vconfig.keyboard != Configuration.KEYBOARD_UNDEFINED) { + assertNotNull(config.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD); + } + } + + // If any entries in appear in the list, sanity check them against all running applications + private void checkErrorListSanity(List<ActivityManager.ProcessErrorStateInfo> errList) { + if (errList == null) return; + + Iterator<ActivityManager.ProcessErrorStateInfo> iter = errList.iterator(); + while (iter.hasNext()) { + ActivityManager.ProcessErrorStateInfo info = iter.next(); + assertNotNull(info); + // sanity checks + assertTrue((info.condition == ActivityManager.ProcessErrorStateInfo.CRASHED) || + (info.condition == ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING)); + // TODO look at each of these and consider a stronger test + // TODO can we cross-check at the process name via some other API? + // TODO is there a better test for strings, e.g. "assertIsLegalString") + assertNotNull(info.processName); + // reasonableness test for info.pid ? + assertNotNull(info.longMsg); + assertNotNull(info.shortMsg); + // is there any reasonable test for the crashData? Probably not. + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/ActivityTests.java b/core/tests/coretests/src/android/app/activity/ActivityTests.java new file mode 100644 index 0000000..c57fe98 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/ActivityTests.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2006 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.activity; + +import junit.framework.TestSuite; + +public class ActivityTests { + public static final boolean DEBUG_LIFECYCLE = false; + + public static TestSuite suite() { + TestSuite suite = new TestSuite(ActivityTests.class.getName()); + + suite.addTestSuite(BroadcastTest.class); + suite.addTestSuite(IntentSenderTest.class); + suite.addTestSuite(ActivityManagerTest.class); + suite.addTestSuite(LaunchTest.class); + suite.addTestSuite(LifecycleTest.class); + suite.addTestSuite(ServiceTest.class); + suite.addTestSuite(MetaDataTest.class); + // Remove temporarily until bug 1171309 is fixed. + //suite.addTestSuite(SubActivityTest.class); + suite.addTestSuite(SetTimeZonePermissionsTest.class); + + return suite; + } +} diff --git a/core/tests/coretests/src/android/app/activity/ActivityTestsBase.java b/core/tests/coretests/src/android/app/activity/ActivityTestsBase.java new file mode 100644 index 0000000..232abe2 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/ActivityTestsBase.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.test.AndroidTestCase; +import android.test.PerformanceTestCase; + +public class ActivityTestsBase extends AndroidTestCase + implements PerformanceTestCase, LaunchpadActivity.CallingTest { + public static final String PERMISSION_GRANTED = + "com.android.frameworks.coretests.permission.TEST_GRANTED"; + public static final String PERMISSION_DENIED = + "com.android.frameworks.coretests.permission.TEST_DENIED"; + + protected Intent mIntent; + + private PerformanceTestCase.Intermediates mIntermediates; + private String mExpecting; + + // Synchronization of activity result. + private boolean mFinished; + private int mResultCode = 0; + private Intent mData; + private RuntimeException mResultStack = null; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mIntent = new Intent(mContext, LaunchpadActivity.class); + mIntermediates = null; + } + + @Override + protected void tearDown() throws Exception { + mIntermediates = null; + super.tearDown(); + } + + public boolean isPerformanceOnly() { + return false; + } + + public void setInternalIterations(int count) { + } + + public void startTiming(boolean realTime) { + if (mIntermediates != null) { + mIntermediates.startTiming(realTime); + } + } + + public void addIntermediate(String name) { + if (mIntermediates != null) { + mIntermediates.addIntermediate(name); + } + } + + public void addIntermediate(String name, long timeInNS) { + if (mIntermediates != null) { + mIntermediates.addIntermediate(name, timeInNS); + } + } + + public void finishTiming(boolean realTime) { + if (mIntermediates != null) { + mIntermediates.finishTiming(realTime); + } + } + + public void activityFinished(int resultCode, Intent data, RuntimeException where) { + finishWithResult(resultCode, data, where); + } + + public Intent editIntent() { + return mIntent; + } + + public Context getContext() { + return mContext; + } + + public int startPerformance(Intermediates intermediates) { + mIntermediates = intermediates; + return 1; + } + + public void finishGood() { + finishWithResult(Activity.RESULT_OK, null); + } + + public void finishBad(String error) { + finishWithResult(Activity.RESULT_CANCELED, (new Intent()).setAction(error)); + } + + public void finishWithResult(int resultCode, Intent data) { + RuntimeException where = new RuntimeException("Original error was here"); + where.fillInStackTrace(); + finishWithResult(resultCode, data, where); + } + + public void finishWithResult(int resultCode, Intent data, RuntimeException where) { + synchronized (this) { + //System.out.println("*** Activity finished!!"); + mResultCode = resultCode; + mData = data; + mResultStack = where; + mFinished = true; + notifyAll(); + } + } + + public int runLaunchpad(String action) { + LaunchpadActivity.setCallingTest(this); + + synchronized (this) { + mIntent.setAction(action); + mFinished = false; + //System.out.println("*** Starting: " + mIntent); + mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(mIntent); + } + + return waitForResultOrThrow(60 * 1000); + } + + public int waitForResultOrThrow(int timeoutMs) { + return waitForResultOrThrow(timeoutMs, null); + } + + public int waitForResultOrThrow(int timeoutMs, String expected) { + int res = waitForResult(timeoutMs, expected); + + if (res == Activity.RESULT_CANCELED) { + if (mResultStack != null) { + throw new RuntimeException( + mData != null ? mData.toString() : "Unable to launch", + mResultStack); + } else { + throw new RuntimeException( + mData != null ? mData.toString() : "Unable to launch"); + } + } + return res; + } + + public int waitForResult(int timeoutMs, String expected) { + mExpecting = expected; + + long endTime = System.currentTimeMillis() + timeoutMs; + + boolean timeout = false; + synchronized (this) { + while (!mFinished) { + long delay = endTime - System.currentTimeMillis(); + if (delay < 0) { + timeout = true; + break; + } + + try { + wait(delay); + } catch (java.lang.InterruptedException e) { + // do nothing + } + } + } + + mFinished = false; + + if (timeout) { + mResultCode = Activity.RESULT_CANCELED; + onTimeout(); + } + return mResultCode; + } + + public int getResultCode() { + return mResultCode; + } + + public Intent getResultData() { + return mData; + } + + public RuntimeException getResultStack() { + return mResultStack; + } + + public void onTimeout() { + String msg = mExpecting == null + ? "Timeout" : ("Timeout while expecting " + mExpecting); + finishWithResult(Activity.RESULT_CANCELED, (new Intent()).setAction(msg)); + } +} + diff --git a/core/tests/coretests/src/android/app/activity/BroadcastTest.java b/core/tests/coretests/src/android/app/activity/BroadcastTest.java new file mode 100644 index 0000000..4b1f9fd --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/BroadcastTest.java @@ -0,0 +1,536 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Activity; +import android.app.ActivityManagerNative; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcel; +import android.test.FlakyTest; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +import java.util.Arrays; + +public class BroadcastTest extends ActivityTestsBase { + public static final int BROADCAST_TIMEOUT = 5 * 1000; + + public static final String BROADCAST_REGISTERED = + "com.android.frameworks.coretests.activity.BROADCAST_REGISTERED"; + public static final String BROADCAST_LOCAL = + "com.android.frameworks.coretests.activity.BROADCAST_LOCAL"; + public static final String BROADCAST_LOCAL_GRANTED = + "com.android.frameworks.coretests.activity.BROADCAST_LOCAL_GRANTED"; + public static final String BROADCAST_LOCAL_DENIED = + "com.android.frameworks.coretests.activity.BROADCAST_LOCAL_DENIED"; + public static final String BROADCAST_REMOTE = + "com.android.frameworks.coretests.activity.BROADCAST_REMOTE"; + public static final String BROADCAST_REMOTE_GRANTED = + "com.android.frameworks.coretests.activity.BROADCAST_REMOTE_GRANTED"; + public static final String BROADCAST_REMOTE_DENIED = + "com.android.frameworks.coretests.activity.BROADCAST_REMOTE_DENIED"; + public static final String BROADCAST_ALL = + "com.android.frameworks.coretests.activity.BROADCAST_ALL"; + public static final String BROADCAST_MULTI = + "com.android.frameworks.coretests.activity.BROADCAST_MULTI"; + public static final String BROADCAST_ABORT = + "com.android.frameworks.coretests.activity.BROADCAST_ABORT"; + + public static final String BROADCAST_STICKY1 = + "com.android.frameworks.coretests.activity.BROADCAST_STICKY1"; + public static final String BROADCAST_STICKY2 = + "com.android.frameworks.coretests.activity.BROADCAST_STICKY2"; + + public static final String BROADCAST_FAIL_REGISTER = + "com.android.frameworks.coretests.activity.BROADCAST_FAIL_REGISTER"; + public static final String BROADCAST_FAIL_BIND = + "com.android.frameworks.coretests.activity.BROADCAST_FAIL_BIND"; + + public static final String RECEIVER_REG = "receiver-reg"; + public static final String RECEIVER_LOCAL = "receiver-local"; + public static final String RECEIVER_REMOTE = "receiver-remote"; + public static final String RECEIVER_ABORT = "receiver-abort"; + public static final String RECEIVER_RESULTS = "receiver-results"; + + public static final String DATA_1 = "one"; + public static final String DATA_2 = "two"; + + public static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; + public static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1; + + private String[] mExpectedReceivers = null; + private int mNextReceiver; + + private String[] mExpectedData = null; + private boolean[] mReceivedData = null; + + boolean mReceiverRegistered = false; + + public void setExpectedReceivers(String[] receivers) { + mExpectedReceivers = receivers; + mNextReceiver = 0; + } + + public void setExpectedData(String[] data) { + mExpectedData = data; + mReceivedData = new boolean[data.length]; + } + + public void onTimeout() { + String msg = "Timeout"; + if (mExpectedReceivers != null && mNextReceiver < mExpectedReceivers.length) { + msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver]; + } + finishBad(msg); + } + + public Intent makeBroadcastIntent(String action) { + Intent intent = new Intent(action, null); + intent.putExtra("caller", mCallTarget); + return intent; + } + + public void finishWithResult(int resultCode, Intent data) { + unregisterMyReceiver(); + super.finishWithResult(resultCode, data); + } + + public final void gotReceive(String name, Intent intent) { + synchronized (this) { + + //System.out.println("Got receive: " + name); + //System.out.println(mNextReceiver + " in " + mExpectedReceivers); + //new RuntimeException("stack").printStackTrace(); + + addIntermediate(name); + + if (mExpectedData != null) { + int n = mExpectedData.length; + int i; + boolean prev = false; + for (i = 0; i < n; i++) { + if (mExpectedData[i].equals(intent.getStringExtra("test"))) { + if (mReceivedData[i]) { + prev = true; + continue; + } + mReceivedData[i] = true; + break; + } + } + if (i >= n) { + if (prev) { + finishBad("Receive got data too many times: " + + intent.getStringExtra("test")); + } else { + finishBad("Receive got unexpected data: " + + intent.getStringExtra("test")); + } + new RuntimeException("stack").printStackTrace(); + return; + } + } + + if (mNextReceiver >= mExpectedReceivers.length) { + finishBad("Got too many onReceiveIntent() calls!"); +// System.out.println("Too many intents received: now at " +// + mNextReceiver + ", expect list: " +// + Arrays.toString(mExpectedReceivers)); + fail("Got too many onReceiveIntent() calls!"); + } else if (!mExpectedReceivers[mNextReceiver].equals(name)) { + finishBad("Receive out of order: got " + name + + " but expected " + + mExpectedReceivers[mNextReceiver]); + fail("Receive out of order: got " + name + + " but expected " + + mExpectedReceivers[mNextReceiver]); + } else { + mNextReceiver++; + if (mNextReceiver == mExpectedReceivers.length) { + finishTest(); + } + } + } + } + + public void registerMyReceiver(IntentFilter filter, String permission) { + mReceiverRegistered = true; + //System.out.println("Registering: " + mReceiver); + getContext().registerReceiver(mReceiver, filter, permission, null); + } + + public void unregisterMyReceiver() { + if (mReceiverRegistered) { + unregisterMyReceiverNoCheck(); + } + } + + public void unregisterMyReceiverNoCheck() { + mReceiverRegistered = false; + //System.out.println("Unregistering: " + mReceiver); + getContext().unregisterReceiver(mReceiver); + } + + public void onRegisteredReceiver(Intent intent) { + gotReceive(RECEIVER_REG, intent); + } + + private Binder mCallTarget = new Binder() { + public boolean onTransact(int code, Parcel data, Parcel reply, + int flags) { + data.setDataPosition(0); + data.enforceInterface(LaunchpadActivity.LAUNCH); + if (code == GOT_RECEIVE_TRANSACTION) { + String name = data.readString(); + gotReceive(name, null); + return true; + } else if (code == ERROR_TRANSACTION) { + finishBad(data.readString()); + return true; + } + return false; + } + }; + + private void finishTest() { + if (mReceiverRegistered) { + addIntermediate("before-unregister"); + unregisterMyReceiver(); + } + finishTiming(true); + finishGood(); + } + + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + //System.out.println("Receive in: " + this + ": " + intent); + onRegisteredReceiver(intent); + } + }; + + // Mark flaky until http://b/issue?id=1191607 is resolved. + @FlakyTest(tolerance=2) + public void testRegistered() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_REGISTERED); + } + + public void testLocal() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_LOCAL); + } + + public void testRemote() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_REMOTE); + } + + public void testAbort() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_ABORT); + } + + @FlakyTest(tolerance=2) + public void testAll() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_ALL); + } + + @FlakyTest(tolerance=2) + public void testMulti() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_MULTI); + } + + private class TestBroadcastReceiver extends BroadcastReceiver { + public boolean mHaveResult = false; + + @Override + public void onReceive(Context context, Intent intent) { + synchronized (BroadcastTest.this) { + mHaveResult = true; + BroadcastTest.this.notifyAll(); + } + } + } + + public void testResult() throws Exception { + TestBroadcastReceiver broadcastReceiver = new TestBroadcastReceiver(); + + synchronized (this) { + Bundle map = new Bundle(); + map.putString("foo", "you"); + map.putString("remove", "me"); + getContext().sendOrderedBroadcast( + new Intent("com.android.frameworks.coretests.activity.BROADCAST_RESULT"), + null, broadcastReceiver, null, 1, "foo", map); + while (!broadcastReceiver.mHaveResult) { + try { + wait(); + } catch (InterruptedException e) { + } + } + + //System.out.println("Code: " + mResultCode + ", data: " + mResultData); + //System.out.println("Extras: " + mResultExtras); + + assertEquals("Incorrect code: " + broadcastReceiver.getResultCode(), + 3, broadcastReceiver.getResultCode()); + + assertEquals("bar", broadcastReceiver.getResultData()); + + Bundle resultExtras = broadcastReceiver.getResultExtras(false); + assertEquals("them", resultExtras.getString("bar")); + assertEquals("you", resultExtras.getString("foo")); + assertNull(resultExtras.getString("remove")); + } + } + + public void testSetSticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.getDefault().unbroadcastIntent(null, intent); + + ActivityManagerNative.broadcastStickyIntent(intent, null); + addIntermediate("finished-broadcast"); + + IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); + Intent sticky = getContext().registerReceiver(null, filter); + assertNotNull("Sticky not found", sticky); + assertEquals(LaunchpadActivity.DATA_1, sticky.getStringExtra("test")); + } + + public void testClearSticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.broadcastStickyIntent(intent, null); + + ActivityManagerNative.getDefault().unbroadcastIntent( + null, new Intent(LaunchpadActivity.BROADCAST_STICKY1, null)); + addIntermediate("finished-unbroadcast"); + + IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); + Intent sticky = getContext().registerReceiver(null, filter); + assertNull("Sticky not found", sticky); + } + + public void testReplaceSticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.broadcastStickyIntent(intent, null); + intent.putExtra("test", LaunchpadActivity.DATA_2); + + ActivityManagerNative.broadcastStickyIntent(intent, null); + addIntermediate("finished-broadcast"); + + IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); + Intent sticky = getContext().registerReceiver(null, filter); + assertNotNull("Sticky not found", sticky); + assertEquals(LaunchpadActivity.DATA_2, sticky.getStringExtra("test")); + } + + // Marking flaky until http://b/issue?id=1191337 is resolved + @FlakyTest(tolerance=2) + public void testReceiveSticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.broadcastStickyIntent(intent, null); + + runLaunchpad(LaunchpadActivity.BROADCAST_STICKY1); + } + + // Marking flaky until http://b/issue?id=1191337 is resolved + @FlakyTest(tolerance=2) + public void testReceive2Sticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.broadcastStickyIntent(intent, null); + intent = new Intent(LaunchpadActivity.BROADCAST_STICKY2, null); + intent.putExtra("test", LaunchpadActivity.DATA_2); + ActivityManagerNative.broadcastStickyIntent(intent, null); + + runLaunchpad(LaunchpadActivity.BROADCAST_STICKY2); + } + + public void testRegisteredReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REG}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_GRANTED); + addIntermediate("after-register"); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRegisteredReceivePermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_DENIED); + addIntermediate("after-register"); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_REGISTERED), + null, finish, null, Activity.RESULT_CANCELED, null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRegisteredBroadcastPermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REG}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); + addIntermediate("after-register"); + getContext().sendBroadcast( + makeBroadcastIntent(BROADCAST_REGISTERED), + PERMISSION_GRANTED); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRegisteredBroadcastPermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); + addIntermediate("after-register"); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_REGISTERED), + PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL_GRANTED)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalReceivePermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_LOCAL_DENIED), + null, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalBroadcastPermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + getContext().sendBroadcast( + makeBroadcastIntent(BROADCAST_LOCAL), + PERMISSION_GRANTED); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalBroadcastPermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_LOCAL), + PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRemoteReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REMOTE}); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE_GRANTED)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRemoteReceivePermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_REMOTE_DENIED), + null, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRemoteBroadcastPermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REMOTE}); + getContext().sendBroadcast( + makeBroadcastIntent(BROADCAST_REMOTE), + PERMISSION_GRANTED); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRemoteBroadcastPermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_REMOTE), + PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testReceiverCanNotRegister() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_REGISTER)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testReceiverCanNotBind() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_BIND)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalUnregisterTwice() throws Exception { + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); + unregisterMyReceiverNoCheck(); + try { + unregisterMyReceiverNoCheck(); + fail("No exception thrown on second unregister"); + } catch (IllegalArgumentException e) { + Log.i("foo", "Unregister exception", e); + } + } +} diff --git a/core/tests/coretests/src/android/app/activity/ClearTop.java b/core/tests/coretests/src/android/app/activity/ClearTop.java new file mode 100644 index 0000000..a5ee2ce --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/ClearTop.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +public class ClearTop extends Activity { + public static final String WAIT_CLEAR_TASK = "waitClearTask"; + + public ClearTop() { + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + //Log.i("foo", "Creating: " + this); + Intent intent = new Intent(getIntent()).setAction(LocalScreen.CLEAR_TASK) + .setClass(this, LocalScreen.class); + startActivity(intent); + } + + @Override + public void onNewIntent(Intent intent) { + //Log.i("foo", "New intent in " + this + ": " + intent); + if (LocalScreen.CLEAR_TASK.equals(intent.getAction())) { + setResult(RESULT_OK); + } else { + setResult(RESULT_CANCELED, new Intent().setAction( + "New intent received " + intent + ", expecting action " + + TestedScreen.CLEAR_TASK)); + } + finish(); + } +} diff --git a/core/tests/coretests/src/android/app/activity/IntentSenderTest.java b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java new file mode 100644 index 0000000..3c30915 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.IntentFilter; +import android.test.suitebuilder.annotation.Suppress; +import android.os.Bundle; +import android.test.suitebuilder.annotation.Suppress; + +public class IntentSenderTest extends BroadcastTest { + + public void testRegisteredReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REG}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_GRANTED); + addIntermediate("after-register"); + PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, + makeBroadcastIntent(BROADCAST_REGISTERED), 0); + is.send(); + waitForResultOrThrow(BROADCAST_TIMEOUT); + is.cancel(); + } + + public void testRegisteredReceivePermissionDenied() throws Exception { + final Intent intent = makeBroadcastIntent(BROADCAST_REGISTERED); + + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_DENIED); + addIntermediate("after-register"); + + PendingIntent.OnFinished finish = new PendingIntent.OnFinished() { + public void onSendFinished(PendingIntent pi, Intent intent, + int resultCode, String resultData, Bundle resultExtras) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, 0); + is.send(Activity.RESULT_CANCELED, finish, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + is.cancel(); + } + + public void testLocalReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, + makeBroadcastIntent(BROADCAST_LOCAL_GRANTED), 0); + is.send(); + waitForResultOrThrow(BROADCAST_TIMEOUT); + is.cancel(); + } + + public void testLocalReceivePermissionDenied() throws Exception { + final Intent intent = makeBroadcastIntent(BROADCAST_LOCAL_DENIED); + + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + PendingIntent.OnFinished finish = new PendingIntent.OnFinished() { + public void onSendFinished(PendingIntent pi, Intent intent, + int resultCode, String resultData, Bundle resultExtras) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, 0); + is.send(Activity.RESULT_CANCELED, finish, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + is.cancel(); + } +} diff --git a/core/tests/coretests/src/android/app/activity/LaunchTest.java b/core/tests/coretests/src/android/app/activity/LaunchTest.java new file mode 100644 index 0000000..5893fd0 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LaunchTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.ComponentName; +import android.test.suitebuilder.annotation.LargeTest; + +public class LaunchTest extends ActivityTestsBase { + + @LargeTest + public void testColdActivity() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), TestedActivity.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testLocalActivity() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), LocalActivity.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testColdScreen() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), TestedScreen.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testLocalScreen() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), LocalScreen.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testForwardResult() throws Exception { + runLaunchpad(LaunchpadActivity.FORWARD_RESULT); + } + + // The following is disabled until we can catch and recover from + // application errors. + public void xxtestBadParcelable() throws Exception { + // All we really care about for this test is that the system + // doesn't crash. + runLaunchpad(LaunchpadActivity.BAD_PARCELABLE); + } + + @LargeTest + public void testClearTopInCreate() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), ClearTop.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testClearTopWhileResumed() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), ClearTop.class)); + mIntent.putExtra(ClearTop.WAIT_CLEAR_TASK, true); + runLaunchpad(LaunchpadActivity.LAUNCH); + } +} + + diff --git a/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java b/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java new file mode 100644 index 0000000..7662456 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java @@ -0,0 +1,588 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; +import android.test.PerformanceTestCase; +import android.util.Log; + +class MyBadParcelable implements Parcelable { + public MyBadParcelable() { + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString("I am bad"); + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<MyBadParcelable> CREATOR + = new Parcelable.Creator<MyBadParcelable>() { + public MyBadParcelable createFromParcel(Parcel in) { + return new MyBadParcelable(in); + } + + public MyBadParcelable[] newArray(int size) { + return new MyBadParcelable[size]; + } + }; + + public MyBadParcelable(Parcel in) { + String nm = in.readString(); + } +} + +public class LaunchpadActivity extends Activity { + public interface CallingTest extends PerformanceTestCase.Intermediates { + public void startTiming(boolean realTime); + public void addIntermediate(String name); + public void addIntermediate(String name, long timeInNS); + public void finishTiming(boolean realTime); + public void activityFinished(int resultCode, Intent data, + RuntimeException where); + } + + // Also used as the Binder interface descriptor string in these tests + public static final String LAUNCH = "com.android.frameworks.coretests.activity.LAUNCH"; + + public static final String FORWARD_RESULT = + "com.android.frameworks.coretests.activity.FORWARD_RESULT"; + public static final String RETURNED_RESULT = + "com.android.frameworks.coretests.activity.RETURNED_RESULT"; + + public static final String BAD_PARCELABLE = + "comcom.android.frameworks.coretests.activity.BAD_PARCELABLE"; + + public static final int LAUNCHED_RESULT = 1; + public static final int FORWARDED_RESULT = 2; + + public static final String LIFECYCLE_BASIC = + "com.android.frameworks.coretests.activity.LIFECYCLE_BASIC"; + public static final String LIFECYCLE_SCREEN = + "com.android.frameworks.coretests.activity.LIFECYCLE_SCREEN"; + public static final String LIFECYCLE_DIALOG = + "com.android.frameworks.coretests.activity.LIFECYCLE_DIALOG"; + public static final String LIFECYCLE_FINISH_CREATE = + "com.android.frameworks.coretests.activity.LIFECYCLE_FINISH_CREATE"; + public static final String LIFECYCLE_FINISH_START = + "com.android.frameworks.coretests.activity.LIFECYCLE_FINISH_START"; + + public static final String BROADCAST_REGISTERED = + "com.android.frameworks.coretests.activity.BROADCAST_REGISTERED"; + public static final String BROADCAST_LOCAL = + "com.android.frameworks.coretests.activity.BROADCAST_LOCAL"; + public static final String BROADCAST_REMOTE = + "com.android.frameworks.coretests.activity.BROADCAST_REMOTE"; + public static final String BROADCAST_ALL = + "com.android.frameworks.coretests.activity.BROADCAST_ALL"; + public static final String BROADCAST_REPEAT = + "com.android.frameworks.coretests.activity.BROADCAST_REPEAT"; + public static final String BROADCAST_MULTI = + "com.android.frameworks.coretests.activity.BROADCAST_MULTI"; + public static final String BROADCAST_ABORT = + "com.android.frameworks.coretests.activity.BROADCAST_ABORT"; + + public static final String BROADCAST_STICKY1 = + "com.android.frameworks.coretests.activity.BROADCAST_STICKY1"; + public static final String BROADCAST_STICKY2 = + "com.android.frameworks.coretests.activity.BROADCAST_STICKY2"; + + public static final String RECEIVER_REG = "receiver-reg"; + public static final String RECEIVER_LOCAL = "receiver-local"; + public static final String RECEIVER_REMOTE = "receiver-remote"; + public static final String RECEIVER_ABORT = "receiver-abort"; + + public static final String DATA_1 = "one"; + public static final String DATA_2 = "two"; + + public static final String ON_START = "onStart"; + public static final String ON_RESTART = "onRestart"; + public static final String ON_RESUME = "onResume"; + public static final String ON_FREEZE = "onSaveInstanceState"; + public static final String ON_PAUSE = "onPause"; + public static final String ON_STOP = "onStop"; + public static final String ON_DESTROY = "onDestroy"; + + public static final String DO_FINISH = "finish"; + public static final String DO_LOCAL_SCREEN = "local-screen"; + public static final String DO_LOCAL_DIALOG = "local-dialog"; + + private boolean mBadParcelable = false; + + private boolean mStarted = false; + private long mStartTime; + + private int mResultCode = RESULT_CANCELED; + private Intent mData = (new Intent()).setAction("No result received"); + private RuntimeException mResultStack = null; + + private String[] mExpectedLifecycle = null; + private int mNextLifecycle; + + private String[] mExpectedReceivers = null; + private int mNextReceiver; + + private String[] mExpectedData = null; + private boolean[] mReceivedData = null; + + boolean mReceiverRegistered = false; + + private static CallingTest sCallingTest = null; + + public static void setCallingTest(CallingTest ct) { + sCallingTest = ct; + } + + public LaunchpadActivity() { + mStartTime = System.currentTimeMillis(); + } + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + String action = getIntent().getAction(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "CREATE lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + if (LIFECYCLE_BASIC.equals(action)) { + setExpectedLifecycle(new String[]{ON_START, ON_RESUME, + DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); + } else if (LIFECYCLE_SCREEN.equals(action)) { + setExpectedLifecycle(new String[]{ON_START, ON_RESUME, + DO_LOCAL_SCREEN, ON_FREEZE, ON_PAUSE, ON_STOP, + ON_RESTART, ON_START, ON_RESUME, + DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); + } else if (LIFECYCLE_DIALOG.equals(action)) { + setExpectedLifecycle(new String[]{ON_START, ON_RESUME, + DO_LOCAL_DIALOG, ON_FREEZE, ON_PAUSE, ON_RESUME, + DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); + } else if (LIFECYCLE_FINISH_CREATE.equals(action)) { + // This one behaves a little differently when running in a group. + if (getParent() == null) { + setExpectedLifecycle(new String[]{ON_DESTROY}); + } else { + setExpectedLifecycle(new String[]{ON_START, ON_STOP, ON_DESTROY}); + } + finish(); + } else if (LIFECYCLE_FINISH_START.equals(action)) { + setExpectedLifecycle(new String[]{ON_START, DO_FINISH, + ON_STOP, ON_DESTROY}); + } + } + + @Override + protected void onStart() { + super.onStart(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "START lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_START); + } + + @Override + protected void onRestart() { + super.onStart(); + checkLifecycle(ON_RESTART); + } + + @Override + protected void onResume() { + super.onResume(); + + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "RESUME lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_RESUME); + + if (!mStarted) { + mStarted = true; + + mHandler.postDelayed(mTimeout, 5 * 1000); + + String action = getIntent().getAction(); + + sCallingTest.startTiming(true); + + if (LAUNCH.equals(action)) { + Intent intent = getIntent(); + intent.setFlags(0); + intent.setComponent((ComponentName) + intent.getParcelableExtra("component")); + //System.out.println("*** Launchpad is starting: comp=" + intent.component); + startActivityForResult(intent, LAUNCHED_RESULT); + } else if (FORWARD_RESULT.equals(action)) { + Intent intent = getIntent(); + intent.setFlags(0); + intent.setClass(this, LocalScreen.class); + startActivityForResult(intent, FORWARDED_RESULT); + } else if (BAD_PARCELABLE.equals(action)) { + mBadParcelable = true; + Intent intent = getIntent(); + intent.setFlags(0); + intent.setClass(this, LocalScreen.class); + startActivityForResult(intent, LAUNCHED_RESULT); + } else if (BROADCAST_REGISTERED.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_REG}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED)); + sCallingTest.addIntermediate("after-register"); + sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED)); + } else if (BROADCAST_LOCAL.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL)); + } else if (BROADCAST_REMOTE.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_REMOTE}); + sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE)); + } else if (BROADCAST_ALL.equals(action)) { + setExpectedReceivers(new String[]{ + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL}); + registerMyReceiver(new IntentFilter(BROADCAST_ALL)); + sCallingTest.addIntermediate("after-register"); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + } else if (BROADCAST_MULTI.equals(action)) { + setExpectedReceivers(new String[]{ + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_LOCAL, RECEIVER_REMOTE, + RECEIVER_LOCAL, RECEIVER_REMOTE, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_LOCAL}); + registerMyReceiver(new IntentFilter(BROADCAST_ALL)); + sCallingTest.addIntermediate("after-register"); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REPEAT), null); + } else if (BROADCAST_ABORT.equals(action)) { + setExpectedReceivers(new String[]{ + RECEIVER_REMOTE, RECEIVER_ABORT}); + registerMyReceiver(new IntentFilter(BROADCAST_ABORT)); + sCallingTest.addIntermediate("after-register"); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ABORT), null); + } else if (BROADCAST_STICKY1.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_REG}); + setExpectedData(new String[]{DATA_1}); + registerMyReceiver(new IntentFilter(BROADCAST_STICKY1)); + sCallingTest.addIntermediate("after-register"); + } else if (BROADCAST_STICKY2.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_REG, RECEIVER_REG}); + setExpectedData(new String[]{DATA_1, DATA_2}); + IntentFilter filter = new IntentFilter(BROADCAST_STICKY1); + filter.addAction(BROADCAST_STICKY2); + registerMyReceiver(filter); + sCallingTest.addIntermediate("after-register"); + } + } + } + + @Override + protected void onSaveInstanceState(Bundle icicle) { + super.onSaveInstanceState(icicle); + checkLifecycle(ON_FREEZE); + if (mBadParcelable) { + icicle.putParcelable("baddy", new MyBadParcelable()); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "PAUSE lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_PAUSE); + } + + @Override + protected void onStop() { + super.onStop(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "STOP lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_STOP); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + switch (requestCode) { + case LAUNCHED_RESULT: + sCallingTest.finishTiming(true); + finishWithResult(resultCode, data); + break; + case FORWARDED_RESULT: + sCallingTest.finishTiming(true); + if (RETURNED_RESULT.equals(data.getAction())) { + finishWithResult(resultCode, data); + } else { + finishWithResult(RESULT_CANCELED, (new Intent()).setAction( + "Bad data returned: " + data)); + } + break; + default: + sCallingTest.finishTiming(true); + finishWithResult(RESULT_CANCELED, (new Intent()).setAction( + "Unexpected request code: " + requestCode)); + break; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "DESTROY lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_DESTROY); + sCallingTest.activityFinished(mResultCode, mData, mResultStack); + } + + private void setExpectedLifecycle(String[] lifecycle) { + mExpectedLifecycle = lifecycle; + mNextLifecycle = 0; + } + + private void checkLifecycle(String where) { + if (mExpectedLifecycle == null) return; + + if (mNextLifecycle >= mExpectedLifecycle.length) { + finishBad("Activity lifecycle incorrect: received " + where + + " but don't expect any more calls"); + mExpectedLifecycle = null; + return; + } + if (!mExpectedLifecycle[mNextLifecycle].equals(where)) { + finishBad("Activity lifecycle incorrect: received " + where + + " but expected " + mExpectedLifecycle[mNextLifecycle] + + " at " + mNextLifecycle); + mExpectedLifecycle = null; + return; + } + + mNextLifecycle++; + + if (mNextLifecycle >= mExpectedLifecycle.length) { + setTestResult(RESULT_OK, null); + return; + } + + String next = mExpectedLifecycle[mNextLifecycle]; + if (where.equals(ON_DESTROY)) { + finishBad("Activity lifecycle incorrect: received " + where + + " but expected more actions (next is " + next + ")"); + mExpectedLifecycle = null; + return; + } else if (next.equals(DO_FINISH)) { + mNextLifecycle++; + if (mNextLifecycle >= mExpectedLifecycle.length) { + setTestResult(RESULT_OK, null); + } + if (!isFinishing()) { + finish(); + } + } else if (next.equals(DO_LOCAL_SCREEN)) { + mNextLifecycle++; + Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH); + intent.setClass(this, LocalScreen.class); + startActivity(intent); + } else if (next.equals(DO_LOCAL_DIALOG)) { + mNextLifecycle++; + Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH); + intent.setClass(this, LocalDialog.class); + startActivity(intent); + } + } + + private void setExpectedReceivers(String[] receivers) { + mExpectedReceivers = receivers; + mNextReceiver = 0; + } + + private void setExpectedData(String[] data) { + mExpectedData = data; + mReceivedData = new boolean[data.length]; + } + + private Intent makeBroadcastIntent(String action) { + Intent intent = new Intent(action, null); + intent.putExtra("caller", mCallTarget); + return intent; + } + + private void finishGood() { + finishWithResult(RESULT_OK, null); + } + + private void finishBad(String error) { + finishWithResult(RESULT_CANCELED, (new Intent()).setAction(error)); + } + + private void finishWithResult(int resultCode, Intent data) { + setTestResult(resultCode, data); + finish(); + } + + private void setTestResult(int resultCode, Intent data) { + mHandler.removeCallbacks(mTimeout); + unregisterMyReceiver(); + mResultCode = resultCode; + mData = data; + mResultStack = new RuntimeException("Original error was here"); + mResultStack.fillInStackTrace(); + } + + private void registerMyReceiver(IntentFilter filter) { + mReceiverRegistered = true; + //System.out.println("Registering: " + mReceiver); + registerReceiver(mReceiver, filter); + } + + private void unregisterMyReceiver() { + if (mReceiverRegistered) { + mReceiverRegistered = false; + //System.out.println("Unregistering: " + mReceiver); + unregisterReceiver(mReceiver); + } + } + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + } + }; + + static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; + static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1; + + private Binder mCallTarget = new Binder() { + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) { + data.setDataPosition(0); + data.enforceInterface(LaunchpadActivity.LAUNCH); + if (code == GOT_RECEIVE_TRANSACTION) { + String name = data.readString(); + gotReceive(name, null); + return true; + } else if (code == ERROR_TRANSACTION) { + finishBad(data.readString()); + return true; + } + return false; + } + }; + + private final void gotReceive(String name, Intent intent) { + synchronized (this) { + + //System.out.println("Got receive: " + name); + //System.out.println(mNextReceiver + " in " + mExpectedReceivers); + //new RuntimeException("stack").printStackTrace(); + + sCallingTest.addIntermediate(mNextReceiver + "-" + name); + + if (mExpectedData != null) { + int n = mExpectedData.length; + int i; + boolean prev = false; + for (i = 0; i < n; i++) { + if (mExpectedData[i].equals(intent.getStringExtra("test"))) { + if (mReceivedData[i]) { + prev = true; + continue; + } + mReceivedData[i] = true; + break; + } + } + if (i >= n) { + if (prev) { + finishBad("Receive got data too many times: " + + intent.getStringExtra("test")); + } else { + finishBad("Receive got unexpected data: " + + intent.getStringExtra("test")); + } + return; + } + } + + if (mNextReceiver >= mExpectedReceivers.length) { + finishBad("Got too many onReceiveIntent() calls!"); +// System.out.println("Too many intents received: now at " +// + mNextReceiver + ", expect list: " +// + Arrays.toString(mExpectedReceivers)); + } else if (!mExpectedReceivers[mNextReceiver].equals(name)) { + finishBad("Receive out of order: got " + name + " but expected " + + mExpectedReceivers[mNextReceiver] + " at " + + mNextReceiver); + } else { + mNextReceiver++; + if (mNextReceiver == mExpectedReceivers.length) { + mHandler.post(mUnregister); + } + } + + } + } + + private Runnable mUnregister = new Runnable() { + public void run() { + if (mReceiverRegistered) { + sCallingTest.addIntermediate("before-unregister"); + unregisterMyReceiver(); + } + sCallingTest.finishTiming(true); + finishGood(); + } + }; + + private Runnable mTimeout = new Runnable() { + public void run() { + Log.i("foo", "**** TIMEOUT"); + String msg = "Timeout"; + if (mExpectedReceivers != null + && mNextReceiver < mExpectedReceivers.length) { + msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver]; + } + finishBad(msg); + } + }; + + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + //System.out.println("Receive in: " + this + ": " + intent); + gotReceive(RECEIVER_REG, intent); + } + }; +} + diff --git a/core/tests/coretests/src/android/app/activity/LaunchpadTabActivity.java b/core/tests/coretests/src/android/app/activity/LaunchpadTabActivity.java new file mode 100644 index 0000000..79b860f --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LaunchpadTabActivity.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.TabActivity; +import android.content.ComponentName; +import android.content.Intent; +import android.os.Bundle; +import android.widget.TabHost; + +public class LaunchpadTabActivity extends TabActivity { + public LaunchpadTabActivity() { + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + Intent tabIntent = new Intent(getIntent()); + tabIntent.setComponent((ComponentName)tabIntent.getParcelableExtra("tab")); + + TabHost th = getTabHost(); + TabHost.TabSpec ts = th.newTabSpec("1"); + ts.setIndicator("One"); + ts.setContent(tabIntent); + th.addTab(ts); + } +} + diff --git a/core/tests/coretests/src/android/app/activity/LifecycleTest.java b/core/tests/coretests/src/android/app/activity/LifecycleTest.java new file mode 100644 index 0000000..768a9a4 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LifecycleTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.ComponentName; +import android.content.Intent; +import android.test.FlakyTest; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; + +public class LifecycleTest extends ActivityTestsBase { + private Intent mTopIntent; + private Intent mTabIntent; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTopIntent = mIntent; + mTabIntent = new Intent(mContext, LaunchpadTabActivity.class); + mTabIntent.putExtra("tab", new ComponentName(mContext, + LaunchpadActivity.class)); + } + + @LargeTest + public void testBasic() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC); + } + + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabBasic() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC); + } + + //Marking flaky until bug 1164344 is fixed. + // @FlakyTest(tolerance=2) + // @LargeTest + public void testScreen() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN); + } + + //Marking flaky until bug 1164344 is fixed. + //@FlakyTest(tolerance=2) + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabScreen() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN); + } + + //flaky test, removing from large suite until 1866891 is fixed + //@LargeTest + public void testDialog() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG); + } + + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabDialog() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG); + } + + @MediumTest + public void testFinishCreate() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_FINISH_CREATE); + } + + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabFinishCreate() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_FINISH_CREATE); + } + + @MediumTest + public void testFinishStart() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_FINISH_START); + } + + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabFinishStart() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_FINISH_START); + } +} diff --git a/core/tests/coretests/src/android/app/activity/LocalActivity.java b/core/tests/coretests/src/android/app/activity/LocalActivity.java new file mode 100644 index 0000000..01f1fb6 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalActivity.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006 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.activity; + +import java.util.Map; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; + +public class LocalActivity extends TestedActivity +{ + public LocalActivity() + { + } +} + diff --git a/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java b/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java new file mode 100644 index 0000000..2120a1d --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +class LocalDeniedReceiver extends BroadcastReceiver { + public LocalDeniedReceiver() { + } + + public void onReceive(Context context, Intent intent) { + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(BroadcastTest.RECEIVER_LOCAL); + caller.transact(BroadcastTest.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/LocalDeniedService.java b/core/tests/coretests/src/android/app/activity/LocalDeniedService.java new file mode 100644 index 0000000..3bdac22 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalDeniedService.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2006 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.activity; + +public class LocalDeniedService extends LocalService +{ +} + diff --git a/core/tests/coretests/src/android/app/activity/LocalDialog.java b/core/tests/coretests/src/android/app/activity/LocalDialog.java new file mode 100644 index 0000000..c92fa43 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalDialog.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006 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.activity; + +import java.util.Map; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; + +public class LocalDialog extends TestedScreen +{ + public LocalDialog() + { + } +} + diff --git a/core/tests/coretests/src/android/app/activity/LocalGrantedReceiver.java b/core/tests/coretests/src/android/app/activity/LocalGrantedReceiver.java new file mode 100644 index 0000000..c9e6ab4 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalGrantedReceiver.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +public class LocalGrantedReceiver extends BroadcastReceiver { + public LocalGrantedReceiver() { + } + + public void onReceive(Context context, Intent intent) { + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(BroadcastTest.RECEIVER_LOCAL); + caller.transact(BroadcastTest.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/LocalGrantedService.java b/core/tests/coretests/src/android/app/activity/LocalGrantedService.java new file mode 100644 index 0000000..7ab0fb4 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalGrantedService.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2006 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.activity; + +public class LocalGrantedService extends LocalService +{ +} + diff --git a/core/tests/coretests/src/android/app/activity/LocalProvider.java b/core/tests/coretests/src/android/app/activity/LocalProvider.java new file mode 100644 index 0000000..085e622 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalProvider.java @@ -0,0 +1,163 @@ +/* + * 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. + */ + +package android.app.activity; + +import android.content.UriMatcher; +import android.content.*; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteQueryBuilder; +import android.net.Uri; +import android.util.Config; +import android.util.Log; + +/** Simple test provider that runs in the local process. */ +public class LocalProvider extends ContentProvider { + private static final String TAG = "LocalProvider"; + + private SQLiteOpenHelper mOpenHelper; + + private static final int DATA = 1; + private static final int DATA_ID = 2; + private static final UriMatcher sURLMatcher = new UriMatcher( + UriMatcher.NO_MATCH); + + static { + sURLMatcher.addURI("*", "data", DATA); + sURLMatcher.addURI("*", "data/#", DATA_ID); + } + + private static class DatabaseHelper extends SQLiteOpenHelper { + private static final String DATABASE_NAME = "local.db"; + private static final int DATABASE_VERSION = 1; + + public DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE data (" + + "_id INTEGER PRIMARY KEY," + + "text TEXT, " + + "integer INTEGER);"); + + // insert alarms + db.execSQL("INSERT INTO data (text, integer) VALUES ('first data', 100);"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { + Log.w(TAG, "Upgrading test database from version " + + oldVersion + " to " + currentVersion + + ", which will destroy all old data"); + db.execSQL("DROP TABLE IF EXISTS data"); + onCreate(db); + } + } + + + public LocalProvider() { + } + + @Override + public boolean onCreate() { + mOpenHelper = new DatabaseHelper(getContext()); + return true; + } + + @Override + public Cursor query(Uri url, String[] projectionIn, String selection, + String[] selectionArgs, String sort) { + SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + + // Generate the body of the query + int match = sURLMatcher.match(url); + switch (match) { + case DATA: + qb.setTables("data"); + break; + case DATA_ID: + qb.setTables("data"); + qb.appendWhere("_id="); + qb.appendWhere(url.getPathSegments().get(1)); + break; + default: + throw new IllegalArgumentException("Unknown URL " + url); + } + + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + Cursor ret = qb.query(db, projectionIn, selection, selectionArgs, + null, null, sort); + + if (ret == null) { + if (Config.LOGD) Log.d(TAG, "Alarms.query: failed"); + } else { + ret.setNotificationUri(getContext().getContentResolver(), url); + } + + return ret; + } + + @Override + public String getType(Uri url) { + int match = sURLMatcher.match(url); + switch (match) { + case DATA: + return "vnd.android.cursor.dir/vnd.google.unit_tests.local"; + case DATA_ID: + return "vnd.android.cursor.item/vnd.google.unit_tests.local"; + default: + throw new IllegalArgumentException("Unknown URL"); + } + } + + @Override + public int update(Uri url, ContentValues values, String where, String[] whereArgs) { + int count; + long rowId = 0; + int match = sURLMatcher.match(url); + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + switch (match) { + case DATA_ID: { + String segment = url.getPathSegments().get(1); + rowId = Long.parseLong(segment); + count = db.update("data", values, "_id=" + rowId, null); + break; + } + default: { + throw new UnsupportedOperationException( + "Cannot update URL: " + url); + } + } + if (Config.LOGD) Log.d(TAG, "*** notifyChange() rowId: " + rowId); + getContext().getContentResolver().notifyChange(url, null); + return count; + } + + + @Override + public Uri insert(Uri url, ContentValues initialValues) { + return null; + } + + @Override + public int delete(Uri url, String where, String[] whereArgs) { + throw new UnsupportedOperationException("delete not supported"); + } +} diff --git a/core/tests/coretests/src/android/app/activity/LocalReceiver.java b/core/tests/coretests/src/android/app/activity/LocalReceiver.java new file mode 100644 index 0000000..bfd543f --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalReceiver.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ReceiverCallNotAllowedException; +import android.content.ServiceConnection; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +public class LocalReceiver extends BroadcastReceiver { + public LocalReceiver() { + } + + public void onReceive(Context context, Intent intent) { + String resultString = LaunchpadActivity.RECEIVER_LOCAL; + if (BroadcastTest.BROADCAST_FAIL_REGISTER.equals(intent.getAction())) { + resultString = "Successfully registered, but expected it to fail"; + try { + context.registerReceiver(this, new IntentFilter("foo.bar")); + context.unregisterReceiver(this); + } catch (ReceiverCallNotAllowedException e) { + //resultString = "This is the correct behavior but not yet implemented"; + resultString = LaunchpadActivity.RECEIVER_LOCAL; + } + } else if (BroadcastTest.BROADCAST_FAIL_BIND.equals(intent.getAction())) { + resultString = "Successfully bound to service, but expected it to fail"; + try { + ServiceConnection sc = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + } + + public void onServiceDisconnected(ComponentName name) { + } + }; + context.bindService(new Intent(context, LocalService.class), sc, 0); + context.unbindService(sc); + } catch (ReceiverCallNotAllowedException e) { + //resultString = "This is the correct behavior but not yet implemented"; + resultString = LaunchpadActivity.RECEIVER_LOCAL; + } + } else if (LaunchpadActivity.BROADCAST_REPEAT.equals(intent.getAction())) { + Intent newIntent = new Intent(intent); + newIntent.setAction(LaunchpadActivity.BROADCAST_LOCAL); + context.sendOrderedBroadcast(newIntent, null); + } + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(resultString); + caller.transact(LaunchpadActivity.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/LocalScreen.java b/core/tests/coretests/src/android/app/activity/LocalScreen.java new file mode 100644 index 0000000..f7c8c33 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalScreen.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006 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.activity; + +import java.util.Map; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; + +public class LocalScreen extends TestedScreen +{ + public LocalScreen() + { + } +} + diff --git a/core/tests/coretests/src/android/app/activity/LocalService.java b/core/tests/coretests/src/android/app/activity/LocalService.java new file mode 100644 index 0000000..c31ca4b --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/LocalService.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; +import android.util.Log; + +public class LocalService extends Service { + private final IBinder mBinder = new Binder() { + + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, + int flags) throws RemoteException { + if (code == ServiceTest.SET_REPORTER_CODE) { + data.enforceInterface(ServiceTest.SERVICE_LOCAL); + mReportObject = data.readStrongBinder(); + return true; + } else { + return super.onTransact(code, data, reply, flags); + } + } + + }; + + private IBinder mReportObject; + private int mStartCount = 1; + + public LocalService() { + } + + @Override + public void onStart(Intent intent, int startId) { + //Log.i("LocalService", "onStart: " + intent); + if (intent.getExtras() != null) { + mReportObject = intent.getExtras().getIBinder(ServiceTest.REPORT_OBJ_NAME); + if (mReportObject != null) { + try { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); + data.writeInt(mStartCount); + mStartCount++; + mReportObject.transact( + ServiceTest.STARTED_CODE, data, null, 0); + data.recycle(); + } catch (RemoteException e) { + } + } + } + } + + @Override + public void onDestroy() { + Log.i("LocalService", "onDestroy: mReportObject=" + mReportObject); + if (mReportObject != null) { + try { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); + mReportObject.transact( + ServiceTest.DESTROYED_CODE, data, null, 0); + data.recycle(); + } catch (RemoteException e) { + } + } + } + + @Override + public IBinder onBind(Intent intent) { + Log.i("LocalService", "onBind: " + intent); + return mBinder; + } + + @Override + public boolean onUnbind(Intent intent) { + Log.i("LocalService", "onUnbind: " + intent); + if (mReportObject != null) { + try { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); + mReportObject.transact( + ServiceTest.UNBIND_CODE, data, null, 0); + data.recycle(); + } catch (RemoteException e) { + } + } + return true; + } + + @Override + public void onRebind(Intent intent) { + Log.i("LocalService", "onUnbind: " + intent); + if (mReportObject != null) { + try { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); + mReportObject.transact( + ServiceTest.REBIND_CODE, data, null, 0); + data.recycle(); + } catch (RemoteException e) { + } + } + } +} diff --git a/core/tests/coretests/src/android/app/activity/MetaDataTest.java b/core/tests/coretests/src/android/app/activity/MetaDataTest.java new file mode 100644 index 0000000..214bc91 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/MetaDataTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.ComponentName; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ServiceInfo; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.os.Bundle; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import com.android.frameworks.coretests.R; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +/** + * Tests for meta-data associated with application components. + */ +public class MetaDataTest extends AndroidTestCase { + + private void checkMetaData(ComponentName cn, PackageItemInfo ci) + throws IOException, XmlPullParserException { + assertNotNull("Unable to find component " + cn, ci); + + Bundle md = ci.metaData; + assertNotNull("No meta data found", md); + + assertEquals("foo", md.getString("com.android.frameworks.coretests.string")); + assertTrue(md.getBoolean("com.android.frameworks.coretests.boolean")); + assertEquals(100, md.getInt("com.android.frameworks.coretests.integer")); + assertEquals(0xff000000, md.getInt("com.android.frameworks.coretests.color")); + + assertEquals((double) 1001, + Math.floor(md.getFloat("com.android.frameworks.coretests.float") * 10 + .5)); + + assertEquals(R.xml.metadata, md.getInt("com.android.frameworks.coretests.reference")); + + XmlResourceParser xml = ci.loadXmlMetaData(mContext.getPackageManager(), + "com.android.frameworks.coretests.reference"); + assertNotNull(xml); + + int type; + while ((type = xml.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + } + assertEquals(XmlPullParser.START_TAG, type); + assertEquals("thedata", xml.getName()); + + // method 1: direct access + final String rawAttr = xml.getAttributeValue(null, "rawText"); + assertEquals("some raw text", rawAttr); + + // method 2: direct access of typed value + final int rawColorIntAttr = xml.getAttributeIntValue(null, "rawColor", 0); + assertEquals(0xffffff00, rawColorIntAttr); + final String rawColorStrAttr = xml.getAttributeValue(null, "rawColor"); + assertEquals("#ffffff00", rawColorStrAttr); + + // method 2: direct access of resource attribute + final String nameSpace = "http://schemas.android.com/apk/res/android"; + final int colorIntAttr = xml.getAttributeIntValue(nameSpace, "color", 0); + assertEquals(0xffff0000, colorIntAttr); + final String colorStrAttr = xml.getAttributeValue(nameSpace, "color"); + assertEquals("#ffff0000", colorStrAttr); + + // method 3: styled access (borrowing an attr from view system here) + TypedArray a = mContext.obtainStyledAttributes(xml, + android.R.styleable.TextView); + String styledAttr = a.getString(android.R.styleable.TextView_text); + assertEquals("text", styledAttr); + a.recycle(); + + xml.close(); + } + + @SmallTest + public void testActivityWithData() throws Exception { + ComponentName cn = new ComponentName(mContext, LocalActivity.class); + ActivityInfo ai = mContext.getPackageManager().getActivityInfo( + cn, PackageManager.GET_META_DATA); + + checkMetaData(cn, ai); + + ai = mContext.getPackageManager().getActivityInfo(cn, 0); + + assertNull("Meta data returned when not requested", ai.metaData); + } + + @SmallTest + public void testReceiverWithData() throws Exception { + ComponentName cn = new ComponentName(mContext, LocalReceiver.class); + ActivityInfo ai = mContext.getPackageManager().getReceiverInfo( + cn, PackageManager.GET_META_DATA); + + checkMetaData(cn, ai); + + ai = mContext.getPackageManager().getReceiverInfo(cn, 0); + + assertNull("Meta data returned when not requested", ai.metaData); + } + + @SmallTest + public void testServiceWithData() throws Exception { + ComponentName cn = new ComponentName(mContext, LocalService.class); + ServiceInfo si = mContext.getPackageManager().getServiceInfo( + cn, PackageManager.GET_META_DATA); + + checkMetaData(cn, si); + + si = mContext.getPackageManager().getServiceInfo(cn, 0); + + assertNull("Meta data returned when not requested", si.metaData); + } + + @MediumTest + public void testProviderWithData() throws Exception { + ComponentName cn = new ComponentName(mContext, LocalProvider.class); + ProviderInfo pi = mContext.getPackageManager().resolveContentProvider( + "com.android.frameworks.coretests.LocalProvider", + PackageManager.GET_META_DATA); + checkMetaData(cn, pi); + + pi = mContext.getPackageManager().resolveContentProvider( + "com.android.frameworks.coretests.LocalProvider", 0); + + assertNull("Meta data returned when not requested", pi.metaData); + } + + @SmallTest + public void testPermissionWithData() throws Exception { + ComponentName cn = new ComponentName("foo", + "com.android.frameworks.coretests.permission.TEST_GRANTED"); + PermissionInfo pi = mContext.getPackageManager().getPermissionInfo( + cn.getClassName(), PackageManager.GET_META_DATA); + checkMetaData(cn, pi); + + pi = mContext.getPackageManager().getPermissionInfo( + cn.getClassName(), 0); + + assertNull("Meta data returned when not requested", pi.metaData); + } +} + + diff --git a/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java b/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java new file mode 100644 index 0000000..7c89346 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +class RemoteDeniedReceiver extends BroadcastReceiver { + public RemoteDeniedReceiver() { + } + + public void onReceive(Context context, Intent intent) { + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(BroadcastTest.RECEIVER_REMOTE); + caller.transact(BroadcastTest.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/RemoteGrantedReceiver.java b/core/tests/coretests/src/android/app/activity/RemoteGrantedReceiver.java new file mode 100644 index 0000000..0eca8f7 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/RemoteGrantedReceiver.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +public class RemoteGrantedReceiver extends BroadcastReceiver { + public RemoteGrantedReceiver() { + } + + public void onReceive(Context context, Intent intent) { + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(BroadcastTest.RECEIVER_REMOTE); + caller.transact(BroadcastTest.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/RemoteReceiver.java b/core/tests/coretests/src/android/app/activity/RemoteReceiver.java new file mode 100644 index 0000000..9608fc4 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/RemoteReceiver.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.Context; +import android.content.Intent; +import android.content.BroadcastReceiver; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +public class RemoteReceiver extends BroadcastReceiver +{ + public RemoteReceiver() + { + } + + public void onReceive(Context context, Intent intent) + { + if (LaunchpadActivity.BROADCAST_REPEAT.equals(intent.getAction())) { + Intent newIntent = new Intent(intent); + newIntent.setAction(LaunchpadActivity.BROADCAST_REMOTE); + context.sendOrderedBroadcast(newIntent, null); + } + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(LaunchpadActivity.RECEIVER_REMOTE); + caller.transact(LaunchpadActivity.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java b/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java new file mode 100644 index 0000000..e969d10 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java @@ -0,0 +1,59 @@ +/* //device/apps/AndroidTests/src/com.android.unit_tests/activity/TestedScreen.java +** +** Copyright 2006, 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.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Process; +import android.util.Log; + +public class RemoteSubActivityScreen extends SubActivityScreen { + Handler mHandler = new Handler(); + boolean mFirst = false; + + public RemoteSubActivityScreen() { + } + + @Override + public void onCreate(Bundle icicle) { + // We are running in a remote process, so want to have the sub-activity + // sending the result back in the original process. + Intent intent = getIntent(); + intent.setClass(this, SubActivityScreen.class); + + super.onCreate(icicle); + + boolean kill = intent.getBooleanExtra("kill", false); + //Log.i("foo", "RemoteSubActivityScreen pid=" + Process.myPid() + // + " kill=" + kill); + + if (kill) { + // After finishing initialization, kill the process! But only if + // this is the first time... + if (icicle == null) { + mHandler.post(new Runnable() { + public void run() { + handleBeforeStopping(); + Process.killProcess(Process.myPid()); + } + }); + } + } + } +} diff --git a/core/tests/coretests/src/android/app/activity/ResultReceiver.java b/core/tests/coretests/src/android/app/activity/ResultReceiver.java new file mode 100644 index 0000000..f7daf2c --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/ResultReceiver.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.Context; +import android.content.Intent; +import android.content.BroadcastReceiver; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Bundle; + +import java.util.Map; + +public class ResultReceiver extends BroadcastReceiver +{ + public ResultReceiver() + { + } + + public void onReceive(Context context, Intent intent) + { + setResultCode(3); + setResultData("bar"); + Bundle map = getResultExtras(false); + map.remove("remove"); + map.putString("bar", "them"); + } +} + diff --git a/core/tests/coretests/src/android/app/activity/SearchableActivity.java b/core/tests/coretests/src/android/app/activity/SearchableActivity.java new file mode 100644 index 0000000..e238572 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/SearchableActivity.java @@ -0,0 +1,30 @@ +/* + * 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.activity; + +import android.app.Activity; +import android.os.Bundle; + +public class SearchableActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + finish(); + } + +} diff --git a/core/tests/coretests/src/android/app/activity/ServiceTest.java b/core/tests/coretests/src/android/app/activity/ServiceTest.java new file mode 100644 index 0000000..d3ae415 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/ServiceTest.java @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Binder; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +// These test binders purport to support an interface whose canonical +// interface name is ServiceTest.SERVICE_LOCAL +// Temporarily suppress, this test is causing unit test suite run to fail +// TODO: remove this suppress +@Suppress +public class ServiceTest extends ActivityTestsBase { + + public static final String SERVICE_LOCAL = + "com.android.frameworks.coretests.activity.SERVICE_LOCAL"; + public static final String SERVICE_LOCAL_GRANTED = + "com.android.frameworks.coretests.activity.SERVICE_LOCAL_GRANTED"; + public static final String SERVICE_LOCAL_DENIED = + "com.android.frameworks.coretests.activity.SERVICE_LOCAL_DENIED"; + + public static final String REPORT_OBJ_NAME = "report"; + + public static final int STARTED_CODE = 1; + public static final int DESTROYED_CODE = 2; + public static final int SET_REPORTER_CODE = 3; + public static final int UNBIND_CODE = 4; + public static final int REBIND_CODE = 5; + + public static final int STATE_START_1 = 0; + public static final int STATE_START_2 = 1; + public static final int STATE_UNBIND = 2; + public static final int STATE_DESTROY = 3; + public static final int STATE_REBIND = 4; + public static final int STATE_UNBIND_ONLY = 5; + public int mStartState; + + public IBinder mStartReceiver = new Binder() { + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, + int flags) throws RemoteException { + //Log.i("ServiceTest", "Received code " + code + " in state " + mStartState); + if (code == STARTED_CODE) { + data.enforceInterface(SERVICE_LOCAL); + int count = data.readInt(); + if (mStartState == STATE_START_1) { + if (count == 1) { + finishGood(); + } else { + finishBad("onStart() again on an object when it should have been the first time"); + } + } else if (mStartState == STATE_START_2) { + if (count == 2) { + finishGood(); + } else { + finishBad("onStart() the first time on an object when it should have been the second time"); + } + } else { + finishBad("onStart() was called when not expected (state="+mStartState+")"); + } + return true; + } else if (code == DESTROYED_CODE) { + data.enforceInterface(SERVICE_LOCAL); + if (mStartState == STATE_DESTROY) { + finishGood(); + } else { + finishBad("onDestroy() was called when not expected (state="+mStartState+")"); + } + return true; + } else if (code == UNBIND_CODE) { + data.enforceInterface(SERVICE_LOCAL); + if (mStartState == STATE_UNBIND) { + mStartState = STATE_DESTROY; + } else if (mStartState == STATE_UNBIND_ONLY) { + finishGood(); + } else { + finishBad("onUnbind() was called when not expected (state="+mStartState+")"); + } + return true; + } else if (code == REBIND_CODE) { + data.enforceInterface(SERVICE_LOCAL); + if (mStartState == STATE_REBIND) { + finishGood(); + } else { + finishBad("onRebind() was called when not expected (state="+mStartState+")"); + } + return true; + } else { + return super.onTransact(code, data, reply, flags); + } + } + }; + + public class EmptyConnection implements ServiceConnection { + public void onServiceConnected(ComponentName name, IBinder service) { + } + + public void onServiceDisconnected(ComponentName name) { + } + } + + public class TestConnection implements ServiceConnection { + private final boolean mExpectDisconnect; + private final boolean mSetReporter; + private boolean mMonitor; + private int mCount; + + public TestConnection(boolean expectDisconnect, boolean setReporter) { + mExpectDisconnect = expectDisconnect; + mSetReporter = setReporter; + mMonitor = !setReporter; + } + + void setMonitor(boolean v) { + mMonitor = v; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + if (mSetReporter) { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(SERVICE_LOCAL); + data.writeStrongBinder(mStartReceiver); + try { + service.transact(SET_REPORTER_CODE, data, null, 0); + } catch (RemoteException e) { + finishBad("DeadObjectException when sending reporting object"); + } + data.recycle(); + } + + if (mMonitor) { + mCount++; + if (mStartState == STATE_START_1) { + if (mCount == 1) { + finishGood(); + } else { + finishBad("onServiceConnected() again on an object when it should have been the first time"); + } + } else if (mStartState == STATE_START_2) { + if (mCount == 2) { + finishGood(); + } else { + finishBad("onServiceConnected() the first time on an object when it should have been the second time"); + } + } else { + finishBad("onServiceConnected() called unexpectedly"); + } + } + } + + public void onServiceDisconnected(ComponentName name) { + if (mMonitor) { + if (mStartState == STATE_DESTROY) { + if (mExpectDisconnect) { + finishGood(); + } else { + finishBad("onServiceDisconnected() when it shouldn't have been"); + } + } else { + finishBad("onServiceDisconnected() called unexpectedly"); + } + } + } + } + + void startExpectResult(Intent service) { + startExpectResult(service, new Bundle()); + } + + void startExpectResult(Intent service, Bundle bundle) { + bundle.putIBinder(REPORT_OBJ_NAME, mStartReceiver); + boolean success = false; + try { + //Log.i("foo", "STATE_START_1"); + mStartState = STATE_START_1; + getContext().startService(new Intent(service).putExtras(bundle)); + waitForResultOrThrow(5 * 1000, "service to start first time"); + //Log.i("foo", "STATE_START_2"); + mStartState = STATE_START_2; + getContext().startService(new Intent(service).putExtras(bundle)); + waitForResultOrThrow(5 * 1000, "service to start second time"); + success = true; + } finally { + if (!success) { + try { + getContext().stopService(service); + } catch (Exception e) { + // eat + } + } + } + //Log.i("foo", "STATE_DESTROY"); + mStartState = STATE_DESTROY; + getContext().stopService(service); + waitForResultOrThrow(5 * 1000, "service to be destroyed"); + } + + void startExpectNoPermission(Intent service) { + try { + getContext().startService(service); + fail("Expected security exception when starting " + service); + } catch (SecurityException e) { + // expected + } + } + + void bindExpectResult(Intent service) { + TestConnection conn = new TestConnection(true, false); + TestConnection conn2 = new TestConnection(false, false); + boolean success = false; + try { + // Expect to see the TestConnection connected. + mStartState = STATE_START_1; + getContext().bindService(service, conn, 0); + getContext().startService(service); + waitForResultOrThrow(5 * 1000, "existing connection to receive service"); + + // Expect to see the second TestConnection connected. + getContext().bindService(service, conn2, 0); + waitForResultOrThrow(5 * 1000, "new connection to receive service"); + + getContext().unbindService(conn2); + success = true; + } finally { + if (!success) { + try { + getContext().stopService(service); + getContext().unbindService(conn); + getContext().unbindService(conn2); + } catch (Exception e) { + // eat + } + } + } + + // Expect to see the TestConnection disconnected. + mStartState = STATE_DESTROY; + getContext().stopService(service); + waitForResultOrThrow(5 * 1000, "existing connection to lose service"); + + getContext().unbindService(conn); + + conn = new TestConnection(true, true); + success = false; + try { + // Expect to see the TestConnection connected. + conn.setMonitor(true); + mStartState = STATE_START_1; + getContext().bindService(service, conn, 0); + getContext().startService(service); + waitForResultOrThrow(5 * 1000, "existing connection to receive service"); + + success = true; + } finally { + if (!success) { + try { + getContext().stopService(service); + getContext().unbindService(conn); + } catch (Exception e) { + // eat + } + } + } + + // Expect to see the service unbind and then destroyed. + conn.setMonitor(false); + mStartState = STATE_UNBIND; + getContext().stopService(service); + waitForResultOrThrow(5 * 1000, "existing connection to lose service"); + + getContext().unbindService(conn); + + conn = new TestConnection(true, true); + success = false; + try { + // Expect to see the TestConnection connected. + conn.setMonitor(true); + mStartState = STATE_START_1; + getContext().bindService(service, conn, 0); + getContext().startService(service); + waitForResultOrThrow(5 * 1000, "existing connection to receive service"); + + success = true; + } finally { + if (!success) { + try { + getContext().stopService(service); + getContext().unbindService(conn); + } catch (Exception e) { + // eat + } + } + } + + // Expect to see the service unbind but not destroyed. + conn.setMonitor(false); + mStartState = STATE_UNBIND_ONLY; + getContext().unbindService(conn); + waitForResultOrThrow(5 * 1000, "existing connection to unbind service"); + + // Expect to see the service rebound. + mStartState = STATE_REBIND; + getContext().bindService(service, conn, 0); + waitForResultOrThrow(5 * 1000, "existing connection to rebind service"); + + // Expect to see the service unbind and then destroyed. + mStartState = STATE_UNBIND; + getContext().stopService(service); + waitForResultOrThrow(5 * 1000, "existing connection to lose service"); + + getContext().unbindService(conn); + } + + void bindAutoExpectResult(Intent service) { + TestConnection conn = new TestConnection(false, true); + boolean success = false; + try { + conn.setMonitor(true); + mStartState = STATE_START_1; + getContext().bindService( + service, conn, Context.BIND_AUTO_CREATE); + waitForResultOrThrow(5 * 1000, "connection to start and receive service"); + success = true; + } finally { + if (!success) { + try { + getContext().unbindService(conn); + } catch (Exception e) { + // eat + } + } + } + mStartState = STATE_UNBIND; + getContext().unbindService(conn); + waitForResultOrThrow(5 * 1000, "disconnecting from service"); + } + + void bindExpectNoPermission(Intent service) { + TestConnection conn = new TestConnection(false, false); + try { + getContext().bindService(service, conn, Context.BIND_AUTO_CREATE); + fail("Expected security exception when binding " + service); + } catch (SecurityException e) { + // expected + } finally { + getContext().unbindService(conn); + } + } + + + @MediumTest + public void testLocalStartClass() throws Exception { + startExpectResult(new Intent(getContext(), LocalService.class)); + } + + @MediumTest + public void testLocalStartAction() throws Exception { + startExpectResult(new Intent(SERVICE_LOCAL)); + } + + @MediumTest + public void testLocalBindClass() throws Exception { + bindExpectResult(new Intent(getContext(), LocalService.class)); + } + + @MediumTest + public void testLocalBindAction() throws Exception { + bindExpectResult(new Intent(SERVICE_LOCAL)); + } + + @MediumTest + public void testLocalBindAutoClass() throws Exception { + bindAutoExpectResult(new Intent(getContext(), LocalService.class)); + } + + @MediumTest + public void testLocalBindAutoAction() throws Exception { + bindAutoExpectResult(new Intent(SERVICE_LOCAL)); + } + + @MediumTest + public void testLocalStartClassPermissionGranted() throws Exception { + startExpectResult(new Intent(getContext(), LocalGrantedService.class)); + } + + @MediumTest + public void testLocalStartActionPermissionGranted() throws Exception { + startExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); + } + + @MediumTest + public void testLocalBindClassPermissionGranted() throws Exception { + bindExpectResult(new Intent(getContext(), LocalGrantedService.class)); + } + + @MediumTest + public void testLocalBindActionPermissionGranted() throws Exception { + bindExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); + } + + @MediumTest + public void testLocalBindAutoClassPermissionGranted() throws Exception { + bindAutoExpectResult(new Intent(getContext(), LocalGrantedService.class)); + } + + @MediumTest + public void testLocalBindAutoActionPermissionGranted() throws Exception { + bindAutoExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); + } + + @MediumTest + public void testLocalStartClassPermissionDenied() throws Exception { + startExpectNoPermission(new Intent(getContext(), LocalDeniedService.class)); + } + + @MediumTest + public void testLocalStartActionPermissionDenied() throws Exception { + startExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED)); + } + + @MediumTest + public void testLocalBindClassPermissionDenied() throws Exception { + bindExpectNoPermission(new Intent(getContext(), LocalDeniedService.class)); + } + + @MediumTest + public void testLocalBindActionPermissionDenied() throws Exception { + bindExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED)); + } + + @MediumTest + public void testLocalUnbindTwice() throws Exception { + EmptyConnection conn = new EmptyConnection(); + getContext().bindService( + new Intent(SERVICE_LOCAL_GRANTED), conn, 0); + getContext().unbindService(conn); + try { + getContext().unbindService(conn); + fail("No exception thrown on second unbind"); + } catch (IllegalArgumentException e) { + //Log.i("foo", "Unbind exception", e); + } + } +} diff --git a/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java b/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java new file mode 100644 index 0000000..41b9547 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008 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.activity; + +import android.app.AlarmManager; +import android.content.Context; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; + +import java.util.TimeZone; + +public class SetTimeZonePermissionsTest extends AndroidTestCase { + + private String[] mZones; + private String mCurrentZone; + private AlarmManager mAlarm; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mZones = TimeZone.getAvailableIDs(); + mCurrentZone = TimeZone.getDefault().getID(); + mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); + } + + /** + * Verify that non-system processes cannot set the time zone. + */ + @LargeTest + public void testSetTimeZonePermissions() { + /** + * Attempt to set several predefined time zones, verifying that the system + * system default time zone has not actually changed from its prior state + * after each attempt. + */ + int max = (mZones.length > 10) ? mZones.length : 10; + assertTrue("No system-defined time zones - test invalid", max > 0); + + for (int i = 0; i < max; i++) { + String tz = mZones[i]; + try { + mAlarm.setTimeZone(tz); + } catch (SecurityException se) { + // Expected failure; no need to handle specially since we're + // about to assert that the test invariant holds: no change + // to the system time zone. + } + + String newZone = TimeZone.getDefault().getID(); + assertEquals("AlarmManager.setTimeZone() succeeded despite lack of permission", + mCurrentZone, + newZone); + } + } +} diff --git a/core/tests/coretests/src/android/app/activity/SubActivityScreen.java b/core/tests/coretests/src/android/app/activity/SubActivityScreen.java new file mode 100644 index 0000000..919c591 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/SubActivityScreen.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.os.Bundle; + +public class SubActivityScreen extends Activity { + static final int NO_RESULT_MODE = 0; + static final int RESULT_MODE = 1; + static final int PENDING_RESULT_MODE = 2; + static final int FINISH_SUB_MODE = 3; + + static final int CHILD_OFFSET = 1000; + + int mMode; + + public SubActivityScreen() { + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + mMode = getIntent().getIntExtra("mode", mMode); + //Log.i("foo", "SubActivityScreen pid=" + Process.myPid() + // + " mode=" + mMode); + + // Move on to the next thing that will generate a result... but only + // if we are being launched for the first time. + if (icicle == null) { + if (mMode == PENDING_RESULT_MODE) { + PendingIntent apr = createPendingResult(1, null, + Intent.FILL_IN_ACTION); + Intent res = new Intent(); + res.putExtra("tkey", "tval"); + res.setAction("test"); + try { + apr.send(this, RESULT_OK, res); + } catch (PendingIntent.CanceledException e) { + } + } else if (mMode < CHILD_OFFSET) { + Intent intent = new Intent(); + intent.setClass(this, SubActivityScreen.class); + intent.putExtra("mode", CHILD_OFFSET+mMode); + //System.out.println("*** Starting from onStart: " + intent); + startActivityForResult(intent, 1); + return; + } + } + } + + @Override + protected void onRestoreInstanceState(Bundle state) { + super.onRestoreInstanceState(state); + } + + @Override + protected void onResume() { + super.onResume(); + + //Log.i("foo", "SubActivityScreen pid=" + Process.myPid() + " onResume"); + + if (mMode >= CHILD_OFFSET) { + // Wait a little bit, to give our parent time to kill itself + // if that is something it is into. + try { + Thread.sleep(500); + } catch (InterruptedException e) { + setResult(RESULT_CANCELED, (new Intent()).setAction("Interrupted!")); + finish(); + return; + } + //System.out.println("Resuming sub-activity: mode=" + mMode); + switch (mMode-CHILD_OFFSET) { + case NO_RESULT_MODE: + finish(); + break; + case RESULT_MODE: + Intent res = new Intent(); + res.putExtra("tkey", "tval"); + res.setAction("test"); + setResult(RESULT_OK, res); + finish(); + break; + case FINISH_SUB_MODE: + break; + } + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + //Log.i("foo", "SubActivityScreen pid=" + Process.myPid() + // + " onActivityResult: req=" + requestCode + // + " res=" + resultCode); + + // Assume success. + setResult(RESULT_OK); + + if (requestCode == 1) { + switch (mMode) { + case NO_RESULT_MODE: + case FINISH_SUB_MODE: + if (resultCode != RESULT_CANCELED) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect result code returned: " + resultCode)); + } + break; + case RESULT_MODE: + case PENDING_RESULT_MODE: + if (resultCode != RESULT_OK) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect result code returned: " + resultCode)); + } else if (data == null) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "null data returned")); + } else if (!("test".equals(data.getAction()))) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect action returned: " + data)); + } else if (!("tval".equals(data.getStringExtra("tkey")))) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect extras returned: " + data.getExtras())); + } + break; + } + } else { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect request code returned: " + requestCode)); + } + + finish(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + @Override + protected void onStop() { + super.onStop(); + handleBeforeStopping(); + } + + public void handleBeforeStopping() { + if (mMode == FINISH_SUB_MODE) { + finishActivity(1); + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/SubActivityTest.java b/core/tests/coretests/src/android/app/activity/SubActivityTest.java new file mode 100644 index 0000000..35dde8a --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/SubActivityTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.test.suitebuilder.annotation.Suppress; +import android.content.ComponentName; + +@Suppress +public class SubActivityTest extends ActivityTestsBase { + + public void testPendingResult() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.PENDING_RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testNoResult() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.NO_RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testResult() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testFinishSub() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.FINISH_SUB_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteNoResult() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.NO_RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteResult() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteFinishSub() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.FINISH_SUB_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteRestartNoResult() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.NO_RESULT_MODE); + mIntent.putExtra("kill", true); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteRestartResult() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.RESULT_MODE); + mIntent.putExtra("kill", true); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteRestartFinishSub() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.FINISH_SUB_MODE); + mIntent.putExtra("kill", true); + runLaunchpad(LaunchpadActivity.LAUNCH); + } +} diff --git a/core/tests/coretests/src/android/app/activity/TestedActivity.java b/core/tests/coretests/src/android/app/activity/TestedActivity.java new file mode 100644 index 0000000..3a1c15f --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/TestedActivity.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; +import android.os.Bundle; + +public class TestedActivity extends Activity +{ + public TestedActivity() + { + } + + public void onCreate(Bundle icicle) + { + super.onCreate(icicle); + } + + protected void onRestoreInstanceState(Bundle state) + { + super.onRestoreInstanceState(state); + } + + protected void onResume() + { + super.onResume(); + Looper.myLooper().myQueue().addIdleHandler(new Idler()); + } + + protected void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + } + + protected void onStop() + { + super.onStop(); + } + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + setResult(RESULT_OK); + finish(); + } + }; + + private class Idler implements MessageQueue.IdleHandler + { + public final boolean queueIdle() + { + //Message m = Message.obtain(); + //mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis()+1000); + setResult(RESULT_OK); + finish(); + return false; + } + } +} + diff --git a/core/tests/coretests/src/android/app/activity/TestedScreen.java b/core/tests/coretests/src/android/app/activity/TestedScreen.java new file mode 100644 index 0000000..1682d1a --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/TestedScreen.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2006 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.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; +import android.os.SystemClock; +import android.os.Bundle; +import android.util.Log; + +public class TestedScreen extends Activity +{ + public static final String WAIT_BEFORE_FINISH = "TestedScreen.WAIT_BEFORE_FINISH"; + public static final String DELIVER_RESULT = "TestedScreen.DELIVER_RESULT"; + public static final String CLEAR_TASK = "TestedScreen.CLEAR_TASK"; + + public TestedScreen() { + } + + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "CREATE tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + if (LaunchpadActivity.FORWARD_RESULT.equals(getIntent().getAction())) { + Intent intent = new Intent(getIntent()); + intent.setAction(DELIVER_RESULT); + intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); + startActivity(intent); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "Finishing tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + finish(); + } else if (DELIVER_RESULT.equals(getIntent().getAction())) { + setResult(RESULT_OK, (new Intent()).setAction( + LaunchpadActivity.RETURNED_RESULT)); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "Finishing tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + finish(); + } else if (CLEAR_TASK.equals(getIntent().getAction())) { + if (!getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) { + launchClearTask(); + } + } + } + + protected void onRestoreInstanceState(Bundle state) { + super.onRestoreInstanceState(state); + } + + protected void onResume() { + super.onResume(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "RESUME tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + if (CLEAR_TASK.equals(getIntent().getAction())) { + if (getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) { + Looper.myLooper().myQueue().addIdleHandler(new Idler()); + } + } else { + Looper.myLooper().myQueue().addIdleHandler(new Idler()); + } + } + + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + protected void onStop() { + super.onStop(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "STOP tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + } + + private void launchClearTask() { + Intent intent = new Intent(getIntent()). + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP). + setClass(this, ClearTop.class); + startActivity(intent); + } + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + if (CLEAR_TASK.equals(getIntent().getAction())) { + launchClearTask(); + } else { + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "Finishing tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + setResult(RESULT_OK); + finish(); + } + } + }; + + private class Idler implements MessageQueue.IdleHandler { + public final boolean queueIdle() { + if (WAIT_BEFORE_FINISH.equals(getIntent().getAction())) { + Message m = Message.obtain(); + mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis()+1000); + } else if (CLEAR_TASK.equals(getIntent().getAction())) { + Message m = Message.obtain(); + mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis()+1000); + } else { + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "Finishing tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + setResult(RESULT_OK); + finish(); + } + return false; + } + } +} + |