diff options
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/app/Activity.java | 13 | ||||
-rw-r--r-- | core/java/android/app/ActivityThread.java | 26 | ||||
-rw-r--r-- | core/java/android/app/Instrumentation.java | 1 | ||||
-rw-r--r-- | core/java/android/app/OnActivityPausedListener.java | 31 | ||||
-rw-r--r-- | core/java/android/nfc/INfcAdapter.aidl | 6 | ||||
-rw-r--r-- | core/java/android/nfc/NfcAdapter.java | 67 |
6 files changed, 135 insertions, 9 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f25c4c3..a54b305 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -632,7 +632,7 @@ public class Activity extends ContextThemeWrapper /*package*/ HashMap<String,Object> mLastNonConfigurationChildInstances; Activity mParent; boolean mCalled; - private boolean mResumed; + /*package*/ boolean mResumed; private boolean mStopped; boolean mFinished; boolean mStartedActivity; @@ -3827,9 +3827,8 @@ public class Activity extends ContextThemeWrapper mLastNonConfigurationInstance = null; - // First call onResume() -before- setting mResumed, so we don't - // send out any status bar / menu notifications the client makes. mCalled = false; + // mResumed is set by the instrumentation mInstrumentation.callActivityOnResume(this); if (!mCalled) { throw new SuperNotCalledException( @@ -3838,7 +3837,6 @@ public class Activity extends ContextThemeWrapper } // Now really resume, and install the current status bar and menu. - mResumed = true; mCalled = false; onPostResume(); if (!mCalled) { @@ -3857,6 +3855,7 @@ public class Activity extends ContextThemeWrapper "Activity " + mComponent.toShortString() + " did not call through to super.onPause()"); } + mResumed = false; } final void performUserLeaving() { @@ -3891,10 +3890,12 @@ public class Activity extends ContextThemeWrapper mStopped = true; } - mResumed = false; } - final boolean isResumed() { + /** + * @hide + */ + public final boolean isResumed() { return mResumed; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 78df780..e3fa32c 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -185,6 +185,9 @@ public final class ActivityThread { final HashMap<IBinder, ProviderClientRecord> mLocalProviders = new HashMap<IBinder, ProviderClientRecord>(); + final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners + = new HashMap<Activity, ArrayList<OnActivityPausedListener>>(); + final GcIdler mGcIdler = new GcIdler(); boolean mGcIdlerScheduled = false; @@ -1424,6 +1427,18 @@ public final class ActivityThread { } } + public void registerOnActivityPausedListener(Activity activity, + OnActivityPausedListener listener) { + synchronized (mOnPauseListeners) { + ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); + if (list == null) { + list = new ArrayList<OnActivityPausedListener>(); + mOnPauseListeners.put(activity, list); + } + list.add(listener); + } + } + public final ActivityInfo resolveActivityInfo(Intent intent) { ActivityInfo aInfo = intent.resolveActivityInfo( mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES); @@ -2333,6 +2348,17 @@ public final class ActivityThread { } } r.paused = true; + + // Notify any outstanding on paused listeners + ArrayList<OnActivityPausedListener> listeners; + synchronized (mOnPauseListeners) { + listeners = mOnPauseListeners.remove(r.activity); + } + int size = (listeners != null ? listeners.size() : 0); + for (int i = 0; i < size; i++) { + listeners.get(i).onPaused(r.activity); + } + return state; } diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index b8c3aa3..5c333a2 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1146,6 +1146,7 @@ public class Instrumentation { * @param activity The activity being resumed. */ public void callActivityOnResume(Activity activity) { + activity.mResumed = true; activity.onResume(); if (mActivityMonitors != null) { diff --git a/core/java/android/app/OnActivityPausedListener.java b/core/java/android/app/OnActivityPausedListener.java new file mode 100644 index 0000000..379f133 --- /dev/null +++ b/core/java/android/app/OnActivityPausedListener.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.app; + +/** + * A listener that is called when an Activity is paused. Since this is tracked client side + * it should not be trusted to represent the exact current state, but can be used as a hint + * for cleanup. + * + * @hide + */ +public interface OnActivityPausedListener { + /** + * Called when the given activity is paused. + */ + public void onPaused(Activity activity); +} diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index a663fb8..cb9fc9d 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -16,6 +16,9 @@ package android.nfc; +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.IntentFilter; import android.nfc.NdefMessage; import android.nfc.Tag; import android.nfc.ILlcpSocket; @@ -44,6 +47,9 @@ interface INfcAdapter NdefMessage localGet(); void localSet(in NdefMessage message); void openTagConnection(in Tag tag); + void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent, + in IntentFilter[] filters); + void disableForegroundDispatch(in ComponentName activity); // Non-public methods // TODO: check and complete diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 769e2d0..c9d6af8 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -18,8 +18,12 @@ package android.nfc; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.app.Activity; import android.app.ActivityThread; +import android.app.OnActivityPausedListener; +import android.app.PendingIntent; import android.content.Context; +import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.nfc.technology.TagTechnology; @@ -211,8 +215,6 @@ public final class NfcAdapter { private static INfcAdapter sService; private static INfcTag sTagService; - private final Context mContext; - /** * Helper to check if this device has FEATURE_NFC, but without using * a context. @@ -308,7 +310,6 @@ public final class NfcAdapter { if (setupService() == null) { throw new UnsupportedOperationException(); } - mContext = context; } /** @@ -410,6 +411,66 @@ public final class NfcAdapter { } } + class ForegroundDispatchPausedListener implements OnActivityPausedListener { + @Override + public void onPaused(Activity activity) { + disableForegroundDispatchInternal(activity, true); + } + } + + /** + * Enables foreground dispatching to the given Activity. This will force all NFC Intents that + * match the given filters to be delivered to the activity bypassing the standard dispatch + * mechanism. + * + * This method must be called from the main thread. + * + * @param activity the Activity to dispatch to + * @param intent the PendingIntent to start for the dispatch + * @param filters the IntentFilters to override dispatching for + * @throws IllegalStateException + */ + public void enableForegroundDispatch(Activity activity, PendingIntent intent, + IntentFilter... filters) { + if (activity == null || intent == null || filters == null) { + throw new NullPointerException(); + } + if (!activity.isResumed()) { + throw new IllegalStateException("Foregorund dispatching can onlly be enabled " + + "when your activity is resumed"); + } + try { + ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, + new ForegroundDispatchPausedListener()); + sService.enableForegroundDispatch(activity.getComponentName(), intent, filters); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } + } + + /** + * Disables foreground activity dispatching setup with + * {@link #enableForegroundDispatch}. This must be called before the Activity returns from + * it's <code>onPause()</code> or this method will throw an IllegalStateException. + * + * This method must be called from the main thread. + */ + public void disableForegroundDispatch(Activity activity) { + disableForegroundDispatchInternal(activity, false); + } + + void disableForegroundDispatchInternal(Activity activity, boolean force) { + try { + sService.disableForegroundDispatch(activity.getComponentName()); + if (!force && !activity.isResumed()) { + throw new IllegalStateException("You must disable forgeground dispatching " + + "while your activity is still resumed"); + } + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } + } + /** * Retrieve a TagTechnology object used to interact with a Tag that is * in field. |