summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Activity.java13
-rw-r--r--core/java/android/app/ActivityThread.java26
-rw-r--r--core/java/android/app/Instrumentation.java1
-rw-r--r--core/java/android/app/OnActivityPausedListener.java31
-rw-r--r--core/java/android/nfc/INfcAdapter.aidl6
-rw-r--r--core/java/android/nfc/NfcAdapter.java67
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.