Merge "Move the IME navigation guard view up to decor." into klp-dev
diff --git a/Android.mk b/Android.mk
index 166db4ee..4e5427a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -165,6 +165,7 @@
core/java/android/print/ILayoutResultCallback.aidl \
core/java/android/print/IPrinterDiscoveryObserver.aidl \
core/java/android/print/IPrintDocumentAdapter.aidl \
+ core/java/android/print/IPrintDocumentAdapterObserver.aidl \
core/java/android/print/IPrintJobStateChangeListener.aidl \
core/java/android/print/IPrintManager.aidl \
core/java/android/print/IPrintSpooler.aidl \
diff --git a/core/java/android/print/IPrintDocumentAdapter.aidl b/core/java/android/print/IPrintDocumentAdapter.aidl
index b12c922..9d384fb 100644
--- a/core/java/android/print/IPrintDocumentAdapter.aidl
+++ b/core/java/android/print/IPrintDocumentAdapter.aidl
@@ -19,6 +19,7 @@
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.print.ILayoutResultCallback;
+import android.print.IPrintDocumentAdapterObserver;
import android.print.IWriteResultCallback;
import android.print.PageRange;
import android.print.PrintAttributes;
@@ -29,6 +30,7 @@
* @hide
*/
oneway interface IPrintDocumentAdapter {
+ void setObserver(in IPrintDocumentAdapterObserver observer);
void start();
void layout(in PrintAttributes oldAttributes, in PrintAttributes newAttributes,
ILayoutResultCallback callback, in Bundle metadata, int sequence);
diff --git a/core/java/android/print/IPrintDocumentAdapterObserver.aidl b/core/java/android/print/IPrintDocumentAdapterObserver.aidl
new file mode 100644
index 0000000..4443df0
--- /dev/null
+++ b/core/java/android/print/IPrintDocumentAdapterObserver.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 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.print;
+
+/**
+ * Interface for observing the state of a print document adapter.
+ *
+ * @hide
+ */
+oneway interface IPrintDocumentAdapterObserver {
+ void onDestroy();
+}
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index dbd8278..955b4d8 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -16,6 +16,8 @@
package android.print;
+import android.app.Activity;
+import android.app.Application.ActivityLifecycleCallbacks;
import android.content.Context;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
@@ -302,8 +304,8 @@
if (TextUtils.isEmpty(printJobName)) {
throw new IllegalArgumentException("priintJobName cannot be empty");
}
- PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(documentAdapter,
- mContext.getMainLooper());
+ PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(
+ mContext, documentAdapter);
try {
Bundle result = mService.print(printJobName, delegate,
attributes, mContext.getPackageName(), mAppId, mUserId);
@@ -369,17 +371,21 @@
return new PrinterDiscoverySession(mService, mContext, mUserId);
}
- private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub {
+ private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub
+ implements ActivityLifecycleCallbacks {
private final Object mLock = new Object();
private CancellationSignal mLayoutOrWriteCancellation;
- private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK -
- // cleared in finish()
+ private Activity mActivity; // Strong reference OK - cleared in finish()
+
+ private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in finish
private Handler mHandler; // Strong reference OK - cleared in finish()
+ private IPrintDocumentAdapterObserver mObserver; // Strong reference OK - cleared in finish
+
private LayoutSpec mLastLayoutSpec;
private WriteSpec mLastWriteSpec;
@@ -390,16 +396,42 @@
private boolean mFinishRequested;
private boolean mFinished;
- public PrintDocumentAdapterDelegate(PrintDocumentAdapter documentAdapter, Looper looper) {
+ private boolean mDestroyed;
+
+ public PrintDocumentAdapterDelegate(Context context,
+ PrintDocumentAdapter documentAdapter) {
+ if (!(context instanceof Activity)) {
+ throw new IllegalStateException("Can print only from an activity");
+ }
+ mActivity = (Activity) context;
mDocumentAdapter = documentAdapter;
- mHandler = new MyHandler(looper);
+ mHandler = new MyHandler(mActivity.getMainLooper());
+ mActivity.getApplication().registerActivityLifecycleCallbacks(this);
+ }
+
+ @Override
+ public void setObserver(IPrintDocumentAdapterObserver observer) {
+ final boolean destroyed;
+ synchronized (mLock) {
+ if (!mDestroyed) {
+ mObserver = observer;
+ }
+ destroyed = mDestroyed;
+ }
+ if (destroyed) {
+ try {
+ observer.onDestroy();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error announcing destroyed state", re);
+ }
+ }
}
@Override
public void start() {
synchronized (mLock) {
- // Started or finished - nothing to do.
- if (mStartReqeusted || mFinishRequested) {
+ // Started called or finish called or destroyed - nothing to do.
+ if (mStartReqeusted || mFinishRequested || mDestroyed) {
return;
}
@@ -412,71 +444,85 @@
@Override
public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
ILayoutResultCallback callback, Bundle metadata, int sequence) {
+ final boolean destroyed;
synchronized (mLock) {
- // Start not called or finish called - nothing to do.
- if (!mStartReqeusted || mFinishRequested) {
- return;
+ destroyed = mDestroyed;
+ // If start called and not finished called and not destroyed - do some work.
+ if (mStartReqeusted && !mFinishRequested && !mDestroyed) {
+ // Layout cancels write and overrides layout.
+ if (mLastWriteSpec != null) {
+ IoUtils.closeQuietly(mLastWriteSpec.fd);
+ mLastWriteSpec = null;
+ }
+
+ mLastLayoutSpec = new LayoutSpec();
+ mLastLayoutSpec.callback = callback;
+ mLastLayoutSpec.oldAttributes = oldAttributes;
+ mLastLayoutSpec.newAttributes = newAttributes;
+ mLastLayoutSpec.metadata = metadata;
+ mLastLayoutSpec.sequence = sequence;
+
+ // Cancel the previous cancellable operation.When the
+ // cancellation completes we will do the pending work.
+ if (cancelPreviousCancellableOperationLocked()) {
+ return;
+ }
+
+ doPendingWorkLocked();
}
-
- // Layout cancels write and overrides layout.
- if (mLastWriteSpec != null) {
- IoUtils.closeQuietly(mLastWriteSpec.fd);
- mLastWriteSpec = null;
+ }
+ if (destroyed) {
+ try {
+ callback.onLayoutFailed(null, sequence);
+ } catch (RemoteException re) {
+ Log.i(LOG_TAG, "Error notifying for cancelled layout", re);
}
-
- mLastLayoutSpec = new LayoutSpec();
- mLastLayoutSpec.callback = callback;
- mLastLayoutSpec.oldAttributes = oldAttributes;
- mLastLayoutSpec.newAttributes = newAttributes;
- mLastLayoutSpec.metadata = metadata;
- mLastLayoutSpec.sequence = sequence;
-
- // Cancel the previous cancellable operation.When the
- // cancellation completes we will do the pending work.
- if (cancelPreviousCancellableOperationLocked()) {
- return;
- }
-
- doPendingWorkLocked();
}
}
@Override
public void write(PageRange[] pages, ParcelFileDescriptor fd,
IWriteResultCallback callback, int sequence) {
+ final boolean destroyed;
synchronized (mLock) {
- // Start not called or finish called - nothing to do.
- if (!mStartReqeusted || mFinishRequested) {
- return;
+ destroyed = mDestroyed;
+ // If start called and not finished called and not destroyed - do some work.
+ if (mStartReqeusted && !mFinishRequested && !mDestroyed) {
+ // Write cancels previous writes.
+ if (mLastWriteSpec != null) {
+ IoUtils.closeQuietly(mLastWriteSpec.fd);
+ mLastWriteSpec = null;
+ }
+
+ mLastWriteSpec = new WriteSpec();
+ mLastWriteSpec.callback = callback;
+ mLastWriteSpec.pages = pages;
+ mLastWriteSpec.fd = fd;
+ mLastWriteSpec.sequence = sequence;
+
+ // Cancel the previous cancellable operation.When the
+ // cancellation completes we will do the pending work.
+ if (cancelPreviousCancellableOperationLocked()) {
+ return;
+ }
+
+ doPendingWorkLocked();
}
-
- // Write cancels previous writes.
- if (mLastWriteSpec != null) {
- IoUtils.closeQuietly(mLastWriteSpec.fd);
- mLastWriteSpec = null;
+ }
+ if (destroyed) {
+ try {
+ callback.onWriteFailed(null, sequence);
+ } catch (RemoteException re) {
+ Log.i(LOG_TAG, "Error notifying for cancelled write", re);
}
-
- mLastWriteSpec = new WriteSpec();
- mLastWriteSpec.callback = callback;
- mLastWriteSpec.pages = pages;
- mLastWriteSpec.fd = fd;
- mLastWriteSpec.sequence = sequence;
-
- // Cancel the previous cancellable operation.When the
- // cancellation completes we will do the pending work.
- if (cancelPreviousCancellableOperationLocked()) {
- return;
- }
-
- doPendingWorkLocked();
}
}
@Override
public void finish() {
synchronized (mLock) {
- // Start not called or finish called - nothing to do.
- if (!mStartReqeusted || mFinishRequested) {
+ // Start not called or finish called or destroyed - nothing to do.
+ if (!mStartReqeusted || mFinishRequested || mDestroyed) {
return;
}
@@ -495,15 +541,78 @@
}
}
+ @Override
+ public void onActivityPaused(Activity activity) {
+ /* do nothing */
+ }
+
+ @Override
+ public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+ /* do nothing */
+ }
+
+ @Override
+ public void onActivityStarted(Activity activity) {
+ /* do nothing */
+ }
+
+ @Override
+ public void onActivityResumed(Activity activity) {
+ /* do nothing */
+ }
+
+ @Override
+ public void onActivityStopped(Activity activity) {
+ /* do nothing */
+ }
+
+ @Override
+ public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+ /* do nothing */
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ // We really care only if the activity is being destroyed to
+ // notify the the print spooler so it can close the print dialog.
+ // Note the the spooler has a death recipient that observes if
+ // this process gets killed so we cover the case of onDestroy not
+ // being called due to this process being killed to reclaim memory.
+ final IPrintDocumentAdapterObserver observer;
+ synchronized (mLock) {
+ if (activity == mActivity) {
+ mDestroyed = true;
+ observer = mObserver;
+ clearLocked();
+ } else {
+ observer = null;
+ activity = null;
+ }
+ }
+ if (observer != null) {
+ activity.getApplication().unregisterActivityLifecycleCallbacks(
+ PrintDocumentAdapterDelegate.this);
+ try {
+ observer.onDestroy();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error announcing destroyed state", re);
+ }
+ }
+ }
+
private boolean isFinished() {
return mDocumentAdapter == null;
}
- private void doFinish() {
+ private void clearLocked() {
+ mActivity = null;
mDocumentAdapter = null;
mHandler = null;
- synchronized (mLock) {
- mLayoutOrWriteCancellation = null;
+ mLayoutOrWriteCancellation = null;
+ mLastLayoutSpec = null;
+ if (mLastWriteSpec != null) {
+ IoUtils.closeQuietly(mLastWriteSpec.fd);
+ mLastWriteSpec = null;
}
}
@@ -564,63 +673,81 @@
}
switch (message.what) {
case MSG_START: {
- mDocumentAdapter.onStart();
- }
- break;
+ final PrintDocumentAdapter adapter;
+ synchronized (mLock) {
+ adapter = mDocumentAdapter;
+ }
+ if (adapter != null) {
+ adapter.onStart();
+ }
+ } break;
case MSG_LAYOUT: {
+ final PrintDocumentAdapter adapter;
final CancellationSignal cancellation;
final LayoutSpec layoutSpec;
synchronized (mLock) {
+ adapter = mDocumentAdapter;
layoutSpec = mLastLayoutSpec;
mLastLayoutSpec = null;
cancellation = new CancellationSignal();
mLayoutOrWriteCancellation = cancellation;
}
- if (layoutSpec != null) {
+ if (layoutSpec != null && adapter != null) {
if (DEBUG) {
Log.i(LOG_TAG, "Performing layout");
}
- mDocumentAdapter.onLayout(layoutSpec.oldAttributes,
+ adapter.onLayout(layoutSpec.oldAttributes,
layoutSpec.newAttributes, cancellation,
new MyLayoutResultCallback(layoutSpec.callback,
layoutSpec.sequence), layoutSpec.metadata);
}
- }
- break;
+ } break;
case MSG_WRITE: {
+ final PrintDocumentAdapter adapter;
final CancellationSignal cancellation;
final WriteSpec writeSpec;
synchronized (mLock) {
+ adapter = mDocumentAdapter;
writeSpec = mLastWriteSpec;
mLastWriteSpec = null;
cancellation = new CancellationSignal();
mLayoutOrWriteCancellation = cancellation;
}
- if (writeSpec != null) {
+ if (writeSpec != null && adapter != null) {
if (DEBUG) {
Log.i(LOG_TAG, "Performing write");
}
- mDocumentAdapter.onWrite(writeSpec.pages, writeSpec.fd,
+ adapter.onWrite(writeSpec.pages, writeSpec.fd,
cancellation, new MyWriteResultCallback(writeSpec.callback,
writeSpec.fd, writeSpec.sequence));
}
- }
- break;
+ } break;
case MSG_FINISH: {
if (DEBUG) {
Log.i(LOG_TAG, "Performing finish");
}
- mDocumentAdapter.onFinish();
- doFinish();
- }
- break;
+ final PrintDocumentAdapter adapter;
+ final Activity activity;
+ synchronized (mLock) {
+ adapter = mDocumentAdapter;
+ activity = mActivity;
+ clearLocked();
+ }
+ if (adapter != null) {
+ adapter.onFinish();
+ }
+ if (activity != null) {
+ activity.getApplication().unregisterActivityLifecycleCallbacks(
+ PrintDocumentAdapterDelegate.this);
+ }
+ } break;
default: {
throw new IllegalArgumentException("Unknown message: "
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 9fc37cf..4f53c1e 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -2540,7 +2540,7 @@
/**
* Class with information if a node is a range. Use
- * {@link RangeInfo#obtain(int, float, float, float) to get an instance.
+ * {@link RangeInfo#obtain(int, float, float, float)} to get an instance.
*/
public static final class RangeInfo {
private static final int MAX_POOL_SIZE = 10;
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
new file mode 100644
index 0000000..bbd3f2b
--- /dev/null
+++ b/core/java/android/webkit/CacheManager.java
@@ -0,0 +1,341 @@
+/*
+ * 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.webkit;
+
+import android.content.Context;
+import android.net.http.Headers;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+
+/**
+ * Manages the HTTP cache used by an application's {@link WebView} instances.
+ * @deprecated Access to the HTTP cache will be removed in a future release.
+ * @hide Since {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+// The class CacheManager provides the persistent cache of content that is
+// received over the network. The component handles parsing of HTTP headers and
+// utilizes the relevant cache headers to determine if the content should be
+// stored and if so, how long it is valid for. Network requests are provided to
+// this component and if they can not be resolved by the cache, the HTTP headers
+// are attached, as appropriate, to the request for revalidation of content. The
+// class also manages the cache size.
+//
+// CacheManager may only be used if your activity contains a WebView.
+@Deprecated
+public final class CacheManager {
+ /**
+ * Represents a resource stored in the HTTP cache. Instances of this class
+ * can be obtained by calling
+ * {@link CacheManager#getCacheFile CacheManager.getCacheFile(String, Map<String, String>))}.
+ *
+ * @deprecated Access to the HTTP cache will be removed in a future release.
+ */
+ @Deprecated
+ public static class CacheResult {
+ // these fields are saved to the database
+ int httpStatusCode;
+ long contentLength;
+ long expires;
+ String expiresString;
+ String localPath;
+ String lastModified;
+ String etag;
+ String mimeType;
+ String location;
+ String encoding;
+ String contentdisposition;
+ String crossDomain;
+
+ // these fields are NOT saved to the database
+ InputStream inStream;
+ OutputStream outStream;
+ File outFile;
+
+ /**
+ * Gets the status code of this cache entry.
+ *
+ * @return the status code of this cache entry
+ */
+ public int getHttpStatusCode() {
+ return httpStatusCode;
+ }
+
+ /**
+ * Gets the content length of this cache entry.
+ *
+ * @return the content length of this cache entry
+ */
+ public long getContentLength() {
+ return contentLength;
+ }
+
+ /**
+ * Gets the path of the file used to store the content of this cache
+ * entry, relative to the base directory of the cache. See
+ * {@link CacheManager#getCacheFileBaseDir CacheManager.getCacheFileBaseDir()}.
+ *
+ * @return the path of the file used to store this cache entry
+ */
+ public String getLocalPath() {
+ return localPath;
+ }
+
+ /**
+ * Gets the expiry date of this cache entry, expressed in milliseconds
+ * since midnight, January 1, 1970 UTC.
+ *
+ * @return the expiry date of this cache entry
+ */
+ public long getExpires() {
+ return expires;
+ }
+
+ /**
+ * Gets the expiry date of this cache entry, expressed as a string.
+ *
+ * @return the expiry date of this cache entry
+ *
+ */
+ public String getExpiresString() {
+ return expiresString;
+ }
+
+ /**
+ * Gets the date at which this cache entry was last modified, expressed
+ * as a string.
+ *
+ * @return the date at which this cache entry was last modified
+ */
+ public String getLastModified() {
+ return lastModified;
+ }
+
+ /**
+ * Gets the entity tag of this cache entry.
+ *
+ * @return the entity tag of this cache entry
+ */
+ public String getETag() {
+ return etag;
+ }
+
+ /**
+ * Gets the MIME type of this cache entry.
+ *
+ * @return the MIME type of this cache entry
+ */
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ /**
+ * Gets the value of the HTTP 'Location' header with which this cache
+ * entry was received.
+ *
+ * @return the HTTP 'Location' header for this cache entry
+ */
+ public String getLocation() {
+ return location;
+ }
+
+ /**
+ * Gets the encoding of this cache entry.
+ *
+ * @return the encoding of this cache entry
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Gets the value of the HTTP 'Content-Disposition' header with which
+ * this cache entry was received.
+ *
+ * @return the HTTP 'Content-Disposition' header for this cache entry
+ *
+ */
+ public String getContentDisposition() {
+ return contentdisposition;
+ }
+
+ /**
+ * Gets the input stream to the content of this cache entry, to allow
+ * content to be read. See
+ * {@link CacheManager#getCacheFile CacheManager.getCacheFile(String, Map<String, String>)}.
+ *
+ * @return an input stream to the content of this cache entry
+ */
+ public InputStream getInputStream() {
+ return inStream;
+ }
+
+ /**
+ * Gets an output stream to the content of this cache entry, to allow
+ * content to be written. See
+ * {@link CacheManager#saveCacheFile CacheManager.saveCacheFile(String, CacheResult)}.
+ *
+ * @return an output stream to the content of this cache entry
+ */
+ // Note that this is always null for objects returned by getCacheFile()!
+ public OutputStream getOutputStream() {
+ return outStream;
+ }
+
+
+ /**
+ * Sets an input stream to the content of this cache entry.
+ *
+ * @param stream an input stream to the content of this cache entry
+ */
+ public void setInputStream(InputStream stream) {
+ this.inStream = stream;
+ }
+
+ /**
+ * Sets the encoding of this cache entry.
+ *
+ * @param encoding the encoding of this cache entry
+ */
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ /**
+ * @hide
+ */
+ public void setContentLength(long contentLength) {
+ this.contentLength = contentLength;
+ }
+ }
+
+ /**
+ * Gets the base directory in which the files used to store the contents of
+ * cache entries are placed. See
+ * {@link CacheManager.CacheResult#getLocalPath CacheManager.CacheResult.getLocalPath()}.
+ *
+ * @return the base directory of the cache
+ * @deprecated This method no longer has any effect and always returns null.
+ */
+ @Deprecated
+ public static File getCacheFileBaseDir() {
+ return null;
+ }
+
+ /**
+ * Gets whether the HTTP cache is disabled.
+ *
+ * @return true if the HTTP cache is disabled
+ * @deprecated This method no longer has any effect and always returns false.
+ */
+ @Deprecated
+ public static boolean cacheDisabled() {
+ return false;
+ }
+
+ /**
+ * Starts a cache transaction. Returns true if this is the only running
+ * transaction. Otherwise, this transaction is nested inside currently
+ * running transactions and false is returned.
+ *
+ * @return true if this is the only running transaction
+ * @deprecated This method no longer has any effect and always returns false.
+ */
+ @Deprecated
+ public static boolean startCacheTransaction() {
+ return false;
+ }
+
+ /**
+ * Ends the innermost cache transaction and returns whether this was the
+ * only running transaction.
+ *
+ * @return true if this was the only running transaction
+ * @deprecated This method no longer has any effect and always returns false.
+ */
+ @Deprecated
+ public static boolean endCacheTransaction() {
+ return false;
+ }
+
+ /**
+ * Gets the cache entry for the specified URL, or null if none is found.
+ * If a non-null value is provided for the HTTP headers map, and the cache
+ * entry needs validation, appropriate headers will be added to the map.
+ * The input stream of the CacheEntry object should be closed by the caller
+ * when access to the underlying file is no longer required.
+ *
+ * @param url the URL for which a cache entry is requested
+ * @param headers a map from HTTP header name to value, to be populated
+ * for the returned cache entry
+ * @return the cache entry for the specified URL
+ * @deprecated This method no longer has any effect and always returns null.
+ */
+ @Deprecated
+ public static CacheResult getCacheFile(String url,
+ Map<String, String> headers) {
+ return null;
+ }
+
+ /**
+ * Adds a cache entry to the HTTP cache for the specicifed URL. Also closes
+ * the cache entry's output stream.
+ *
+ * @param url the URL for which the cache entry should be added
+ * @param cacheResult the cache entry to add
+ * @deprecated Access to the HTTP cache will be removed in a future release.
+ */
+ @Deprecated
+ public static void saveCacheFile(String url, CacheResult cacheResult) {
+ saveCacheFile(url, 0, cacheResult);
+ }
+
+ static void saveCacheFile(String url, long postIdentifier,
+ CacheResult cacheRet) {
+ try {
+ cacheRet.outStream.close();
+ } catch (IOException e) {
+ return;
+ }
+
+ // This method is exposed in the public API but the API provides no
+ // way to obtain a new CacheResult object with a non-null output
+ // stream ...
+ // - CacheResult objects returned by getCacheFile() have a null
+ // output stream.
+ // - new CacheResult objects have a null output stream and no
+ // setter is provided.
+ // Since this method throws a null pointer exception in this case,
+ // it is effectively useless from the point of view of the public
+ // API.
+ //
+ // With the Chromium HTTP stack we continue to throw the same
+ // exception for 'backwards compatibility' with the Android HTTP
+ // stack.
+ //
+ // This method is not used from within this package, and for public API
+ // use, we should already have thrown an exception above.
+ assert false;
+ }
+}
diff --git a/core/java/android/webkit/PluginData.java b/core/java/android/webkit/PluginData.java
new file mode 100644
index 0000000..88fc9b7
--- /dev/null
+++ b/core/java/android/webkit/PluginData.java
@@ -0,0 +1,141 @@
+/*
+ * 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.webkit;
+
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * This class encapsulates the content generated by a plugin. The
+ * data itself is meant to be loaded into webkit via the
+ * PluginContentLoader class, which needs to be able to construct an
+ * HTTP response. For this, it needs a stream with the response body,
+ * the length of the body, the response headers, and the response
+ * status code. The PluginData class is the container for all these
+ * parts.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+@Deprecated
+public final class PluginData {
+ /**
+ * The content stream.
+ */
+ private InputStream mStream;
+ /**
+ * The content length.
+ */
+ private long mContentLength;
+ /**
+ * The associated HTTP response headers stored as a map of
+ * lowercase header name to [ unmodified header name, header value].
+ * TODO: This design was always a hack. Remove (involves updating
+ * the Gears C++ side).
+ */
+ private Map<String, String[]> mHeaders;
+
+ /**
+ * The associated HTTP response code.
+ */
+ private int mStatusCode;
+
+ /**
+ * Creates a PluginData instance.
+ *
+ * @param stream The stream that supplies content for the plugin.
+ * @param length The length of the plugin content.
+ * @param headers The response headers. Map of
+ * lowercase header name to [ unmodified header name, header value]
+ * @param length The HTTP response status code.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public PluginData(
+ InputStream stream,
+ long length,
+ Map<String, String[]> headers,
+ int code) {
+ mStream = stream;
+ mContentLength = length;
+ mHeaders = headers;
+ mStatusCode = code;
+ }
+
+ /**
+ * Returns the input stream that contains the plugin content.
+ *
+ * @return An InputStream instance with the plugin content.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public InputStream getInputStream() {
+ return mStream;
+ }
+
+ /**
+ * Returns the length of the plugin content.
+ *
+ * @return the length of the plugin content.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public long getContentLength() {
+ return mContentLength;
+ }
+
+ /**
+ * Returns the HTTP response headers associated with the plugin
+ * content.
+ *
+ * @return A Map<String, String[]> containing all headers. The
+ * mapping is 'lowercase header name' to ['unmodified header
+ * name', header value].
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public Map<String, String[]> getHeaders() {
+ return mHeaders;
+ }
+
+ /**
+ * Returns the HTTP status code for the response.
+ *
+ * @return The HTTP statue code, e.g 200.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public int getStatusCode() {
+ return mStatusCode;
+ }
+}
diff --git a/core/java/android/webkit/UrlInterceptHandler.java b/core/java/android/webkit/UrlInterceptHandler.java
new file mode 100644
index 0000000..59fc0cb
--- /dev/null
+++ b/core/java/android/webkit/UrlInterceptHandler.java
@@ -0,0 +1,60 @@
+/*
+ * 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.webkit;
+
+import android.webkit.CacheManager.CacheResult;
+import android.webkit.PluginData;
+import java.util.Map;
+
+/**
+ * @hide
+ * @deprecated This interface was inteded to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+@Deprecated
+public interface UrlInterceptHandler {
+
+ /**
+ * Given an URL, returns the CacheResult which contains the
+ * surrogate response for the request, or null if the handler is
+ * not interested.
+ *
+ * @param url URL string.
+ * @param headers The headers associated with the request. May be null.
+ * @return The CacheResult containing the surrogate response.
+ *
+ * @hide
+ * @deprecated Do not use, this interface is deprecated.
+ */
+ @Deprecated
+ public CacheResult service(String url, Map<String, String> headers);
+
+ /**
+ * Given an URL, returns the PluginData which contains the
+ * surrogate response for the request, or null if the handler is
+ * not interested.
+ *
+ * @param url URL string.
+ * @param headers The headers associated with the request. May be null.
+ * @return The PluginData containing the surrogate response.
+ *
+ * @hide
+ * @deprecated Do not use, this interface is deprecated.
+ */
+ @Deprecated
+ public PluginData getPluginData(String url, Map<String, String> headers);
+}
diff --git a/core/java/android/webkit/UrlInterceptRegistry.java b/core/java/android/webkit/UrlInterceptRegistry.java
new file mode 100644
index 0000000..bdf6747
--- /dev/null
+++ b/core/java/android/webkit/UrlInterceptRegistry.java
@@ -0,0 +1,167 @@
+/*
+ * 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.webkit;
+
+import android.webkit.CacheManager.CacheResult;
+import android.webkit.PluginData;
+import android.webkit.UrlInterceptHandler;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+
+/**
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+@Deprecated
+public final class UrlInterceptRegistry {
+
+ private final static String LOGTAG = "intercept";
+
+ private static boolean mDisabled = false;
+
+ private static LinkedList mHandlerList;
+
+ private static synchronized LinkedList getHandlers() {
+ if(mHandlerList == null)
+ mHandlerList = new LinkedList<UrlInterceptHandler>();
+ return mHandlerList;
+ }
+
+ /**
+ * set the flag to control whether url intercept is enabled or disabled
+ *
+ * @param disabled true to disable the cache
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public static synchronized void setUrlInterceptDisabled(boolean disabled) {
+ mDisabled = disabled;
+ }
+
+ /**
+ * get the state of the url intercept, enabled or disabled
+ *
+ * @return return if it is disabled
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public static synchronized boolean urlInterceptDisabled() {
+ return mDisabled;
+ }
+
+ /**
+ * Register a new UrlInterceptHandler. This handler will be called
+ * before any that were previously registered.
+ *
+ * @param handler The new UrlInterceptHandler object
+ * @return true if the handler was not previously registered.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public static synchronized boolean registerHandler(
+ UrlInterceptHandler handler) {
+ if (!getHandlers().contains(handler)) {
+ getHandlers().addFirst(handler);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Unregister a previously registered UrlInterceptHandler.
+ *
+ * @param handler A previously registered UrlInterceptHandler.
+ * @return true if the handler was found and removed from the list.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public static synchronized boolean unregisterHandler(
+ UrlInterceptHandler handler) {
+ return getHandlers().remove(handler);
+ }
+
+ /**
+ * Given an url, returns the CacheResult of the first
+ * UrlInterceptHandler interested, or null if none are.
+ *
+ * @return A CacheResult containing surrogate content.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public static synchronized CacheResult getSurrogate(
+ String url, Map<String, String> headers) {
+ if (urlInterceptDisabled()) {
+ return null;
+ }
+ Iterator iter = getHandlers().listIterator();
+ while (iter.hasNext()) {
+ UrlInterceptHandler handler = (UrlInterceptHandler) iter.next();
+ CacheResult result = handler.service(url, headers);
+ if (result != null) {
+ return result;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Given an url, returns the PluginData of the first
+ * UrlInterceptHandler interested, or null if none are or if
+ * intercepts are disabled.
+ *
+ * @return A PluginData instance containing surrogate content.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+ @Deprecated
+ public static synchronized PluginData getPluginData(
+ String url, Map<String, String> headers) {
+ if (urlInterceptDisabled()) {
+ return null;
+ }
+ Iterator iter = getHandlers().listIterator();
+ while (iter.hasNext()) {
+ UrlInterceptHandler handler = (UrlInterceptHandler) iter.next();
+ PluginData data = handler.getPluginData(url, headers);
+ if (data != null) {
+ return data;
+ }
+ }
+ return null;
+ }
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index e94cf18..fdc06a6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -16,6 +16,10 @@
package com.android.keyguard;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
+
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -51,9 +55,6 @@
import android.view.View;
import android.view.WindowManager;
import android.widget.RemoteViews.OnClickHandler;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
import java.io.File;
import java.lang.ref.WeakReference;
@@ -279,7 +280,7 @@
if (newState != mTransportState) {
mTransportState = newState;
if (DEBUGXPORT) Log.v(TAG, "update widget: transport state changed");
- KeyguardHostView.this.postShowAppropriateWidgetPage();
+ KeyguardHostView.this.post(mSwitchPageRunnable);
}
}
@Override
@@ -291,7 +292,7 @@
if (newState != mTransportState) {
mTransportState = newState;
if (DEBUGXPORT) Log.v(TAG, "update widget: play state changed");
- KeyguardHostView.this.postShowAppropriateWidgetPage();
+ KeyguardHostView.this.post(mSwitchPageRunnable);
}
}
}
@@ -495,7 +496,6 @@
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- removeCallbacks(mSwitchPageRunnable);
mAppWidgetHost.stopListening();
KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
}
@@ -1438,7 +1438,7 @@
mAppWidgetToShow = ss.appWidgetToShow;
setInsets(ss.insets);
if (DEBUG) Log.d(TAG, "onRestoreInstanceState, transport=" + mTransportState);
- postShowAppropriateWidgetPage();
+ post(mSwitchPageRunnable);
}
@Override
@@ -1471,22 +1471,13 @@
}
}
- void showAppropriateWidgetPage() {
+ private void showAppropriateWidgetPage() {
int state = mTransportState;
ensureTransportPresentOrRemoved(state);
- if (mAppWidgetContainer.isLayoutRequested()) {
- postShowAppropriateWidgetPage();
- return;
- }
int pageToShow = getAppropriateWidgetPage(state);
mAppWidgetContainer.setCurrentPage(pageToShow);
}
- void postShowAppropriateWidgetPage() {
- removeCallbacks(mSwitchPageRunnable);
- post(mSwitchPageRunnable);
- }
-
/**
* Examines the current state and adds the transport to the widget pager when the state changes.
*
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
index e07e0d0..704af6e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
@@ -40,6 +40,7 @@
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.TextClock;
+
import com.android.internal.widget.LockPatternUtils;
import java.util.ArrayList;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index ee5ff16..787b59a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -40,6 +40,7 @@
import android.os.RemoteException;
import android.print.ILayoutResultCallback;
import android.print.IPrintDocumentAdapter;
+import android.print.IPrintDocumentAdapterObserver;
import android.print.IWriteResultCallback;
import android.print.PageRange;
import android.print.PrintAttributes;
@@ -201,6 +202,14 @@
throw new IllegalArgumentException("PrintDocumentAdapter cannot be null");
}
+ try {
+ IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter)
+ .setObserver(new PrintDocumentAdapterObserver(this));
+ } catch (RemoteException re) {
+ finish();
+ return;
+ }
+
PrintAttributes attributes = printJob.getAttributes();
if (attributes != null) {
mCurrPrintAttributes.copyFrom(attributes);
@@ -249,27 +258,29 @@
// We can safely do the work in here since at this point
// the system is bound to our (spooler) process which
// guarantees that this process will not be killed.
- if (mController.hasStarted()) {
+ if (mController != null && mController.hasStarted()) {
mController.finish();
}
- if (mEditor.isPrintConfirmed() && mController.isFinished()) {
- mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId,
- PrintJobInfo.STATE_QUEUED, null);
+ if (mEditor != null && mEditor.isPrintConfirmed()
+ && mController != null && mController.isFinished()) {
+ mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId,
+ PrintJobInfo.STATE_QUEUED, null);
} else {
mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId,
PrintJobInfo.STATE_CANCELED, null);
}
- mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
if (mGeneratingPrintJobDialog != null) {
mGeneratingPrintJobDialog.dismiss();
mGeneratingPrintJobDialog = null;
}
+ mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
mSpoolerProvider.destroy();
super.onDestroy();
}
public boolean onTouchEvent(MotionEvent event) {
- if (!mEditor.isPrintConfirmed() && mEditor.shouldCloseOnTouch(event)) {
+ if (mController != null && mEditor != null &&
+ !mEditor.isPrintConfirmed() && mEditor.shouldCloseOnTouch(event)) {
if (!mController.isWorking()) {
PrintJobConfigActivity.this.finish();
}
@@ -287,17 +298,19 @@
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- if (mEditor.isShwoingGeneratingPrintJobUi()) {
+ if (mController != null && mEditor != null) {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ if (mEditor.isShwoingGeneratingPrintJobUi()) {
+ return true;
+ }
+ if (event.isTracking() && !event.isCanceled()) {
+ if (!mController.isWorking()) {
+ PrintJobConfigActivity.this.finish();
+ }
+ }
+ mEditor.cancel();
return true;
}
- if (event.isTracking() && !event.isCanceled()) {
- if (!mController.isWorking()) {
- PrintJobConfigActivity.this.finish();
- }
- }
- mEditor.cancel();
- return true;
}
return super.onKeyUp(keyCode, event);
}
@@ -2701,4 +2714,32 @@
/* do noting - we are in the same process */
}
}
+
+ private static final class PrintDocumentAdapterObserver
+ extends IPrintDocumentAdapterObserver.Stub {
+ private final WeakReference<PrintJobConfigActivity> mWeakActvity;
+
+ public PrintDocumentAdapterObserver(PrintJobConfigActivity activity) {
+ mWeakActvity = new WeakReference<PrintJobConfigActivity>(activity);
+ }
+
+ @Override
+ public void onDestroy() {
+ final PrintJobConfigActivity activity = mWeakActvity.get();
+ if (activity != null) {
+ activity.mController.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (activity.mController != null) {
+ activity.mController.cancel();
+ }
+ if (activity.mEditor != null) {
+ activity.mEditor.cancel();
+ }
+ activity.finish();
+ }
+ });
+ }
+ }
+ }
}