summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml22
-rw-r--r--core/java/android/app/ActivityThread.java28
-rw-r--r--core/java/android/app/SearchDialog.java3
-rw-r--r--core/java/android/content/Intent.java10
-rw-r--r--core/java/android/server/BluetoothEventLoop.java4
-rw-r--r--core/java/android/view/WindowManager.java18
-rw-r--r--core/java/android/view/WindowManagerPolicy.java13
-rw-r--r--core/java/android/webkit/BrowserFrame.java4
-rw-r--r--core/java/android/webkit/CallbackProxy.java11
-rwxr-xr-xcore/java/android/webkit/GeolocationPermissions.java147
-rw-r--r--core/java/android/webkit/GoogleLocationSettingManager.java88
-rw-r--r--core/java/android/webkit/PluginManager.java126
-rw-r--r--core/java/android/webkit/ValueCallback.java29
-rw-r--r--core/java/android/webkit/WebChromeClient.java4
-rw-r--r--core/java/android/webkit/WebSettings.java25
-rw-r--r--core/java/android/webkit/WebStorage.java263
-rw-r--r--core/java/android/webkit/WebView.java4
-rw-r--r--core/java/android/webkit/WebViewCore.java59
-rw-r--r--core/java/android/widget/ScrollView.java15
-rw-r--r--core/java/android/widget/TextView.java41
-rw-r--r--core/java/com/android/internal/widget/RotarySelector.java259
-rw-r--r--libs/rs/rsContext.cpp4
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java23
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java51
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java15
-rw-r--r--services/java/com/android/server/BackupManagerService.java33
-rw-r--r--services/java/com/android/server/DockObserver.java3
-rw-r--r--services/java/com/android/server/WindowManagerService.java96
28 files changed, 1000 insertions, 398 deletions
diff --git a/api/current.xml b/api/current.xml
index fa54a10..68a1c76 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -36906,6 +36906,17 @@
visibility="public"
>
</field>
+<field name="METADATA_DOCK_HOME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.dock_home&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="URI_INTENT_SCHEME"
type="int"
transient="false"
@@ -160428,6 +160439,17 @@
visibility="public"
>
</field>
+<field name="FLAG_DISMISS_KEYGUARD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4194304"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="FLAG_DITHER"
type="int"
transient="false"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8142d1a..6acd665 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1765,6 +1765,7 @@ public final class ActivityThread {
public static final int CREATE_BACKUP_AGENT = 128;
public static final int DESTROY_BACKUP_AGENT = 129;
public static final int SUICIDE = 130;
+ public static final int REMOVE_PROVIDER = 131;
String codeToString(int code) {
if (localLOGV) {
switch (code) {
@@ -1799,6 +1800,7 @@ public final class ActivityThread {
case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
case SUICIDE: return "SUICIDE";
+ case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
}
}
return "(unknown)";
@@ -1911,9 +1913,10 @@ public final class ActivityThread {
handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
break;
case SUICIDE:
- {
- Process.killProcess(Process.myPid());
- }
+ Process.killProcess(Process.myPid());
+ break;
+ case REMOVE_PROVIDER:
+ completeRemoveProvider((IContentProvider)msg.obj);
break;
}
}
@@ -4029,15 +4032,28 @@ public final class ActivityThread {
} else {
prc.count--;
if(prc.count == 0) {
- mProviderRefCountMap.remove(jBinder);
- //invoke removeProvider to dereference provider
- removeProviderLocked(provider);
+ // Schedule the actual remove asynchronously, since we
+ // don't know the context this will be called in.
+ Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
+ mH.sendMessage(msg);
} //end if
} //end else
} //end synchronized
return true;
}
+ final void completeRemoveProvider(IContentProvider provider) {
+ IBinder jBinder = provider.asBinder();
+ synchronized(mProviderMap) {
+ ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
+ if(prc != null && prc.count == 0) {
+ mProviderRefCountMap.remove(jBinder);
+ //invoke removeProvider to dereference provider
+ removeProviderLocked(provider);
+ }
+ }
+ }
+
public final void removeProviderLocked(IContentProvider provider) {
if (provider == null) {
return;
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index c0a0480..a2c95f4 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -1617,6 +1617,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
// Now build the Intent
Intent intent = new Intent(action);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ // We need CLEAR_TOP to avoid reusing an old task that has other activities
+ // on top of the one we want.
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (data != null) {
intent.setData(data);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index f6ca50d..5fb5768 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1885,7 +1885,7 @@ public class Intent implements Parcelable {
"android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST";
/**
* An activity to run when device is inserted into a car dock.
- * Used with {@link #ACTION_MAIN} to launch an activity.
+ * Used with {@link #ACTION_MAIN} to launch an activity.
* To monitor dock state, use {@link #ACTION_DOCK_EVENT} instead.
*/
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
@@ -2056,6 +2056,12 @@ public class Intent implements Parcelable {
public static final int EXTRA_DOCK_STATE_CAR = 2;
/**
+ * Boolean that can be supplied as meta-data with a dock activity, to
+ * indicate that the dock should take over the home key when it is active.
+ */
+ public static final String METADATA_DOCK_HOME = "android.dock_home";
+
+ /**
* Used as a parcelable extra field in {@link #ACTION_APP_ERROR}, containing
* the bug report.
*
@@ -3605,7 +3611,7 @@ public class Intent implements Parcelable {
}
} else {
ResolveInfo info = pm.resolveActivity(
- this, PackageManager.MATCH_DEFAULT_ONLY);
+ this, PackageManager.MATCH_DEFAULT_ONLY | flags);
if (info != null) {
ai = info.activityInfo;
}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index f9ab31c..f3bc3a6 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -247,7 +247,6 @@ class BluetoothEventLoop {
addDevice(address, properties);
}
}
- mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDING);
return;
}
@@ -404,6 +403,9 @@ class BluetoothEventLoop {
mBluetoothService.cancelPairingUserInput(address);
return null;
}
+ // Set state to BONDING, for incoming connections it will be set here.
+ // For outgoing connections, it gets set when call createBond.
+ mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDING);
return address;
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index f67c4aa..396e380 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -488,7 +488,10 @@ public interface WindowManager extends ViewManager {
* is locked. This will let application windows take precedence over
* key guard or any other lock screens. Can be used with
* {@link #FLAG_KEEP_SCREEN_ON} to turn screen on and display windows
- * directly before showing the key guard window
+ * directly before showing the key guard window. Can be used with
+ * {@link #FLAG_DISMISS_KEYGUARD} to automatically fully dismisss
+ * non-secure keyguards. This flag only applies to the top-most
+ * full-screen window.
*/
public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
@@ -506,6 +509,19 @@ public interface WindowManager extends ViewManager {
* up the device) to turn the screen on. */
public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
+ /** Window flag: when set the window will cause the keyguard to
+ * be dismissed, only if it is not a secure lock keyguard. Because such
+ * a keyguard is not needed for security, it will never re-appear if
+ * the user navigates to another window (in contrast to
+ * {@link #FLAG_SHOW_WHEN_LOCKED}, which will only temporarily
+ * hide both secure and non-secure keyguards but ensure they reappear
+ * when the user moves to another UI that doesn't hide them).
+ * If the keyguard is currently active and is secure (requires an
+ * unlock pattern) than the user will still need to confirm it before
+ * seeing this window, unless {@link #FLAG_SHOW_WHEN_LOCKED} has
+ * also been set. */
+ public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
+
/** Window flag: special flag to limit the size of the window to be
* original size ([320x480] x density). Used to create window for applications
* running under compatibility mode.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index cc5aeb1..1923743 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -602,11 +602,18 @@ public interface WindowManagerPolicy {
* returned, all windows given to layoutWindow() <em>must</em> have had a
* frame assigned.
*
- * @return Return true if layout state may have changed (so that another
- * layout will be performed).
+ * @return Return any bit set of {@link #FINISH_LAYOUT_REDO_LAYOUT}
+ * and {@link #FINISH_LAYOUT_REDO_CONFIG}.
*/
- public boolean finishLayoutLw();
+ public int finishLayoutLw();
+ /** Layout state may have changed (so another layout will be performed) */
+ static final int FINISH_LAYOUT_REDO_LAYOUT = 0x0001;
+ /** Configuration state may have changed */
+ static final int FINISH_LAYOUT_REDO_CONFIG = 0x0002;
+ /** Wallpaper may need to move */
+ static final int FINISH_LAYOUT_REDO_WALLPAPER = 0x0004;
+
/**
* Called when animation of the windows is about to start.
*
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 4204a1a..e233a02 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -605,8 +605,8 @@ class BrowserFrame extends Handler {
}
// Called by JNI when an apple-touch-icon attribute was found.
- private void didReceiveTouchIconUrl(String url) {
- mCallbackProxy.onReceivedTouchIconUrl(url);
+ private void didReceiveTouchIconUrl(String url, boolean precomposed) {
+ mCallbackProxy.onReceivedTouchIconUrl(url, precomposed);
}
/**
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index b051675..1ec769b 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -249,7 +249,7 @@ class CallbackProxy extends Handler {
case RECEIVED_TOUCH_ICON_URL:
if (mWebChromeClient != null) {
mWebChromeClient.onReceivedTouchIconUrl(mWebView,
- (String) msg.obj);
+ (String) msg.obj, msg.arg1 == 1);
}
break;
@@ -1065,19 +1065,22 @@ class CallbackProxy extends Handler {
sendMessage(obtainMessage(RECEIVED_ICON, icon));
}
- /* package */ void onReceivedTouchIconUrl(String url) {
+ /* package */ void onReceivedTouchIconUrl(String url, boolean precomposed) {
// We should have a current item but we do not want to crash so check
// for null.
WebHistoryItem i = mBackForwardList.getCurrentItem();
if (i != null) {
- i.setTouchIconUrl(url);
+ if (precomposed || i.getTouchIconUrl() != null) {
+ i.setTouchIconUrl(url);
+ }
}
// Do an unsynchronized quick check to avoid posting if no callback has
// been set.
if (mWebChromeClient == null) {
return;
}
- sendMessage(obtainMessage(RECEIVED_TOUCH_ICON_URL, url));
+ sendMessage(obtainMessage(RECEIVED_TOUCH_ICON_URL,
+ precomposed ? 1 : 0, 0, url));
}
public void onReceivedTitle(String title) {
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
index e985ccc..c0cac01 100755
--- a/core/java/android/webkit/GeolocationPermissions.java
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -19,10 +19,9 @@ package android.webkit;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
@@ -47,15 +46,13 @@ public final class GeolocationPermissions {
private static GeolocationPermissions sInstance;
private Handler mHandler;
+ private Handler mUIHandler;
// Members used to transfer the origins and permissions between threads.
private Set<String> mOrigins;
private boolean mAllowed;
private Set<String> mOriginsToClear;
private Set<String> mOriginsToAllow;
- private static Lock mLock = new ReentrantLock();
- private static boolean mUpdated;
- private static Condition mUpdatedCondition = mLock.newCondition();
// Message ids
static final int GET_ORIGINS = 0;
@@ -64,6 +61,15 @@ public final class GeolocationPermissions {
static final int ALLOW = 3;
static final int CLEAR_ALL = 4;
+ // Message ids on the UI thread
+ static final int RETURN_ORIGINS = 0;
+ static final int RETURN_ALLOWED = 1;
+
+ private static final String ORIGINS = "origins";
+ private static final String ORIGIN = "origin";
+ private static final String CALLBACK = "callback";
+ private static final String ALLOWED = "allowed";
+
/**
* Gets the singleton instance of the class.
*/
@@ -75,22 +81,62 @@ public final class GeolocationPermissions {
}
/**
+ * Creates the UI message handler. Must be called on the UI thread.
+ */
+ public void createUIHandler() {
+ if (mUIHandler == null) {
+ mUIHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ // Runs on the UI thread.
+ switch (msg.what) {
+ case RETURN_ORIGINS: {
+ Map values = (Map) msg.obj;
+ Set origins = (Set) values.get(ORIGINS);
+ ValueCallback<Set> callback = (ValueCallback<Set>) values.get(CALLBACK);
+ callback.onReceiveValue(origins);
+ } break;
+ case RETURN_ALLOWED: {
+ Map values = (Map) msg.obj;
+ Boolean allowed = (Boolean) values.get(ALLOWED);
+ ValueCallback<Boolean> callback = (ValueCallback<Boolean>) values.get(CALLBACK);
+ callback.onReceiveValue(allowed);
+ } break;
+ }
+ }
+ };
+ }
+ }
+
+ /**
* Creates the message handler. Must be called on the WebKit thread.
*/
public void createHandler() {
- mLock.lock();
if (mHandler == null) {
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// Runs on the WebKit thread.
switch (msg.what) {
- case GET_ORIGINS:
+ case GET_ORIGINS: {
getOriginsImpl();
- break;
- case GET_ALLOWED:
- getAllowedImpl((String) msg.obj);
- break;
+ ValueCallback callback = (ValueCallback) msg.obj;
+ Set origins = new HashSet(mOrigins);
+ Map values = new HashMap<String, Object>();
+ values.put(CALLBACK, callback);
+ values.put(ORIGINS, origins);
+ postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
+ } break;
+ case GET_ALLOWED: {
+ Map values = (Map) msg.obj;
+ String origin = (String) values.get(ORIGIN);
+ ValueCallback callback = (ValueCallback) values.get(CALLBACK);
+ getAllowedImpl(origin);
+ Map retValues = new HashMap<String, Object>();
+ retValues.put(CALLBACK, callback);
+ retValues.put(ALLOWED, new Boolean(mAllowed));
+ postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues));
+ } break;
case CLEAR:
nativeClear((String) msg.obj);
break;
@@ -115,7 +161,6 @@ public final class GeolocationPermissions {
}
}
}
- mLock.unlock();
}
/**
@@ -127,29 +172,31 @@ public final class GeolocationPermissions {
}
/**
+ * Utility function to send a message to the handler on the UI thread
+ */
+ private void postUIMessage(Message msg) {
+ if (mUIHandler != null) {
+ mUIHandler.sendMessage(msg);
+ }
+ }
+
+ /**
* Gets the set of origins for which Geolocation permissions are stored.
* Note that we represent the origins as strings. These are created using
* WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules'
* (Database, Geolocation etc) do so, it's safe to match up origins for the
* purposes of displaying UI.
*/
- public Set getOrigins() {
- // Called on the UI thread.
- Set origins = null;
- mLock.lock();
- try {
- mUpdated = false;
- postMessage(Message.obtain(null, GET_ORIGINS));
- while (!mUpdated) {
- mUpdatedCondition.await();
+ public void getOrigins(ValueCallback<Set> callback) {
+ if (callback != null) {
+ if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+ getOriginsImpl();
+ Set origins = new HashSet(mOrigins);
+ callback.onReceiveValue(origins);
+ } else {
+ postMessage(Message.obtain(null, GET_ORIGINS, callback));
}
- origins = mOrigins;
- } catch (InterruptedException e) {
- Log.e(TAG, "Exception while waiting for update", e);
- } finally {
- mLock.unlock();
}
- return origins;
}
/**
@@ -157,33 +204,29 @@ public final class GeolocationPermissions {
*/
private void getOriginsImpl() {
// Called on the WebKit thread.
- mLock.lock();
mOrigins = nativeGetOrigins();
- mUpdated = true;
- mUpdatedCondition.signal();
- mLock.unlock();
}
/**
* Gets the permission state for the specified origin.
*/
- public boolean getAllowed(String origin) {
- // Called on the UI thread.
- boolean allowed = false;
- mLock.lock();
- try {
- mUpdated = false;
- postMessage(Message.obtain(null, GET_ALLOWED, origin));
- while (!mUpdated) {
- mUpdatedCondition.await();
- }
- allowed = mAllowed;
- } catch (InterruptedException e) {
- Log.e(TAG, "Exception while waiting for update", e);
- } finally {
- mLock.unlock();
+ public void getAllowed(String origin, ValueCallback<Boolean> callback) {
+ if (callback == null) {
+ return;
+ }
+ if (origin == null) {
+ callback.onReceiveValue(null);
+ return;
+ }
+ if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+ getAllowedImpl(origin);
+ callback.onReceiveValue(new Boolean(mAllowed));
+ } else {
+ Map values = new HashMap<String, Object>();
+ values.put(ORIGIN, origin);
+ values.put(CALLBACK, callback);
+ postMessage(Message.obtain(null, GET_ALLOWED, values));
}
- return allowed;
}
/**
@@ -191,11 +234,7 @@ public final class GeolocationPermissions {
*/
private void getAllowedImpl(String origin) {
// Called on the WebKit thread.
- mLock.lock();
mAllowed = nativeGetAllowed(origin);
- mUpdated = true;
- mUpdatedCondition.signal();
- mLock.unlock();
}
/**
@@ -205,7 +244,6 @@ public final class GeolocationPermissions {
*/
public void clear(String origin) {
// Called on the UI thread.
- mLock.lock();
if (mHandler == null) {
if (mOriginsToClear == null) {
mOriginsToClear = new HashSet<String>();
@@ -217,7 +255,6 @@ public final class GeolocationPermissions {
} else {
postMessage(Message.obtain(null, CLEAR, origin));
}
- mLock.unlock();
}
/**
@@ -227,7 +264,6 @@ public final class GeolocationPermissions {
*/
public void allow(String origin) {
// Called on the UI thread.
- mLock.lock();
if (mHandler == null) {
if (mOriginsToAllow == null) {
mOriginsToAllow = new HashSet<String>();
@@ -239,7 +275,6 @@ public final class GeolocationPermissions {
} else {
postMessage(Message.obtain(null, ALLOW, origin));
}
- mLock.unlock();
}
/**
diff --git a/core/java/android/webkit/GoogleLocationSettingManager.java b/core/java/android/webkit/GoogleLocationSettingManager.java
index fe7fce6..1b6e77c 100644
--- a/core/java/android/webkit/GoogleLocationSettingManager.java
+++ b/core/java/android/webkit/GoogleLocationSettingManager.java
@@ -35,8 +35,6 @@ import java.util.HashSet;
* @hide pending API council review
*/
class GoogleLocationSettingManager {
- // The application context.
- private Context mContext;
// The observer used to listen to the system setting.
private GoogleLocationSettingObserver mSettingObserver;
@@ -48,6 +46,8 @@ class GoogleLocationSettingManager {
// by the browser.
private final static String LAST_READ_USE_LOCATION_FOR_SERVICES =
"lastReadUseLocationForServices";
+ // The Browser package name.
+ private static final String BROWSER_PACKAGE_NAME = "com.android.browser";
// The Google origins we consider.
private static HashSet<String> sGoogleOrigins;
static {
@@ -57,38 +57,72 @@ class GoogleLocationSettingManager {
sGoogleOrigins.add("http://www.google.co.uk");
}
- GoogleLocationSettingManager(Context context) {
- mContext = context;
+ private static GoogleLocationSettingManager sGoogleLocationSettingManager = null;
+ private static int sRefCount = 0;
+
+ static GoogleLocationSettingManager getInstance() {
+ if (sGoogleLocationSettingManager == null) {
+ sGoogleLocationSettingManager = new GoogleLocationSettingManager();
+ }
+ return sGoogleLocationSettingManager;
}
+ private GoogleLocationSettingManager() {}
+
/**
* Starts the manager. Checks whether the setting has changed and
* installs an observer to listen for future changes.
*/
- public void start() {
- maybeApplySetting();
-
+ public void start(Context context) {
+ // Are we running in the browser?
+ if (context == null || !BROWSER_PACKAGE_NAME.equals(context.getPackageName())) {
+ return;
+ }
+ // Increase the refCount
+ sRefCount++;
+ // Are we already registered?
+ if (mSettingObserver != null) {
+ return;
+ }
+ // Read and apply the settings if needed.
+ maybeApplySetting(context);
+ // Register to receive notifications when the system settings change.
mSettingObserver = new GoogleLocationSettingObserver();
- mSettingObserver.observe();
+ mSettingObserver.observe(context);
}
/**
+ * Stops the manager.
+ */
+ public void stop() {
+ // Are we already registered?
+ if (mSettingObserver == null) {
+ return;
+ }
+ if (--sRefCount == 0) {
+ mSettingObserver.doNotObserve();
+ mSettingObserver = null;
+ }
+ }
+ /**
* Checks to see if the system setting has changed and if so,
* updates the Geolocation permissions accordingly.
+ * @param the Application context
*/
- private void maybeApplySetting() {
- int setting = getSystemSetting();
- if (settingChanged(setting)) {
+ private void maybeApplySetting(Context context) {
+ int setting = getSystemSetting(context);
+ if (settingChanged(setting, context)) {
applySetting(setting);
}
}
/**
* Gets the current system setting for 'Use location for Google services'.
+ * @param the Application context
* @return The system setting.
*/
- private int getSystemSetting() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
+ private int getSystemSetting(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.USE_LOCATION_FOR_SERVICES,
sSystemSettingFalse);
}
@@ -97,12 +131,13 @@ class GoogleLocationSettingManager {
* Determines whether the supplied setting has changed from the last
* value read by the browser.
* @param setting The setting.
+ * @param the Application context
* @return Whether the setting has changed from the last value read
* by the browser.
*/
- private boolean settingChanged(int setting) {
+ private boolean settingChanged(int setting, Context context) {
SharedPreferences preferences =
- PreferenceManager.getDefaultSharedPreferences(mContext);
+ PreferenceManager.getDefaultSharedPreferences(context);
// Default to false. If the system setting is false the first time it is ever read by the
// browser, there's nothing to do.
int lastReadSetting = sSystemSettingFalse;
@@ -137,20 +172,35 @@ class GoogleLocationSettingManager {
* This class implements an observer to listen for changes to the
* system setting.
*/
- class GoogleLocationSettingObserver extends ContentObserver {
+ private class GoogleLocationSettingObserver extends ContentObserver {
+ private Context mContext;
+
GoogleLocationSettingObserver() {
super(new Handler());
}
- void observe() {
- ContentResolver resolver = mContext.getContentResolver();
+ void observe(Context context) {
+ if (mContext != null) {
+ return;
+ }
+ ContentResolver resolver = context.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.USE_LOCATION_FOR_SERVICES), false, this);
+ mContext = context;
+ }
+
+ void doNotObserve() {
+ if (mContext == null) {
+ return;
+ }
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ mContext = null;
}
@Override
public void onChange(boolean selfChange) {
- maybeApplySetting();
+ maybeApplySetting(mContext);
}
}
}
diff --git a/core/java/android/webkit/PluginManager.java b/core/java/android/webkit/PluginManager.java
index 32eea5f..766bd75 100644
--- a/core/java/android/webkit/PluginManager.java
+++ b/core/java/android/webkit/PluginManager.java
@@ -63,8 +63,11 @@ public class PluginManager {
private final Context mContext;
+ private ArrayList<PackageInfo> mPackageInfoCache;
+
private PluginManager(Context context) {
mContext = context;
+ mPackageInfoCache = new ArrayList<PackageInfo>();
}
public static synchronized PluginManager getInstance(Context context) {
@@ -92,65 +95,94 @@ public class PluginManager {
}
String[] getPluginDirectories() {
+
ArrayList<String> directories = new ArrayList<String>();
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> plugins = pm.queryIntentServices(new Intent(
PLUGIN_ACTION), PackageManager.GET_SERVICES);
- for (ResolveInfo info : plugins) {
- ServiceInfo serviceInfo = info.serviceInfo;
- if (serviceInfo == null) {
- Log.w(LOGTAG, "Ignore bad plugin");
- continue;
- }
- PackageInfo pkgInfo;
- try {
- pkgInfo = pm.getPackageInfo(serviceInfo.packageName,
- PackageManager.GET_PERMISSIONS
- | PackageManager.GET_SIGNATURES);
- } catch (NameNotFoundException e) {
- Log.w(LOGTAG, "Cant find plugin: " + serviceInfo.packageName);
- continue;
- }
- if (pkgInfo == null) {
- continue;
- }
- String directory = pkgInfo.applicationInfo.dataDir + "/lib";
- if (directories.contains(directory)) {
- continue;
- }
- String permissions[] = pkgInfo.requestedPermissions;
- if (permissions == null) {
- continue;
- }
- boolean permissionOk = false;
- for (String permit : permissions) {
- if (PLUGIN_PERMISSION.equals(permit)) {
- permissionOk = true;
+
+ synchronized(mPackageInfoCache) {
+
+ // clear the list of existing packageInfo objects
+ mPackageInfoCache.clear();
+
+ for (ResolveInfo info : plugins) {
+ ServiceInfo serviceInfo = info.serviceInfo;
+ if (serviceInfo == null) {
+ Log.w(LOGTAG, "Ignore bad plugin");
+ continue;
+ }
+ PackageInfo pkgInfo;
+ try {
+ pkgInfo = pm.getPackageInfo(serviceInfo.packageName,
+ PackageManager.GET_PERMISSIONS
+ | PackageManager.GET_SIGNATURES);
+ } catch (NameNotFoundException e) {
+ Log.w(LOGTAG, "Cant find plugin: " + serviceInfo.packageName);
+ continue;
+ }
+ if (pkgInfo == null) {
+ continue;
+ }
+ String directory = pkgInfo.applicationInfo.dataDir + "/lib";
+ if (directories.contains(directory)) {
+ continue;
+ }
+ String permissions[] = pkgInfo.requestedPermissions;
+ if (permissions == null) {
+ continue;
+ }
+ boolean permissionOk = false;
+ for (String permit : permissions) {
+ if (PLUGIN_PERMISSION.equals(permit)) {
+ permissionOk = true;
+ break;
+ }
+ }
+ if (!permissionOk) {
+ continue;
+ }
+ Signature signatures[] = pkgInfo.signatures;
+ if (signatures == null) {
+ continue;
+ }
+ boolean signatureMatch = false;
+ for (Signature signature : signatures) {
+ // TODO: check signature against Google provided one
+ signatureMatch = true;
break;
}
+ if (!signatureMatch) {
+ continue;
+ }
+ mPackageInfoCache.add(pkgInfo);
+ directories.add(directory);
}
- if (!permissionOk) {
- continue;
- }
- Signature signatures[] = pkgInfo.signatures;
- if (signatures == null) {
- continue;
- }
- boolean signatureMatch = false;
- for (Signature signature : signatures) {
- // TODO: check signature against Google provided one
- signatureMatch = true;
- break;
- }
- if (!signatureMatch) {
- continue;
- }
- directories.add(directory);
}
return directories.toArray(new String[directories.size()]);
}
+ String getPluginsAPKName(String pluginLib) {
+
+ // basic error checking on input params
+ if (pluginLib == null || pluginLib.length() == 0) {
+ return null;
+ }
+
+ // must be synchronized to ensure the consistency of the cache
+ synchronized(mPackageInfoCache) {
+ for (PackageInfo pkgInfo : mPackageInfoCache) {
+ if (pluginLib.startsWith(pkgInfo.applicationInfo.dataDir)) {
+ return pkgInfo.packageName;
+ }
+ }
+ }
+
+ // if no apk was found then return null
+ return null;
+ }
+
String getPluginSharedDataDirectory() {
return mContext.getDir("plugins", 0).getPath();
}
diff --git a/core/java/android/webkit/ValueCallback.java b/core/java/android/webkit/ValueCallback.java
new file mode 100644
index 0000000..d8c5cdc
--- /dev/null
+++ b/core/java/android/webkit/ValueCallback.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * A callback interface used to returns values asynchronously
+ *
+ * @hide pending council approval
+ */
+public interface ValueCallback<T> {
+ /**
+ * Invoked when we have the result
+ */
+ public void onReceiveValue(T value);
+};
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 0e08514..1ae1d85 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -48,9 +48,11 @@ public class WebChromeClient {
* Notify the host application of the url for an apple-touch-icon.
* @param view The WebView that initiated the callback.
* @param url The icon url.
+ * @param precomposed True if the url is for a precomposed touch icon.
* @hide pending council approval
*/
- public void onReceivedTouchIconUrl(WebView view, String url) {}
+ public void onReceivedTouchIconUrl(WebView view, String url,
+ boolean precomposed) {}
/**
* A callback interface used by the host application to notify
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 3c43fd1..0cfcb95 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -190,12 +190,8 @@ public class WebSettings {
private boolean mAllowFileAccess = true;
private boolean mLoadWithOverviewMode = false;
- // Manages interaction of the system setting 'Location & security - Share
- // with Google' and the browser.
- static GoogleLocationSettingManager sGoogleLocationSettingManager;
-
// private WebSettings, not accessible by the host activity
- private int mDoubleTapToastCount = 3;
+ static private int mDoubleTapToastCount = 3;
private static final String PREF_FILE = "WebViewSettings";
private static final String DOUBLE_TAP_TOAST_COUNT = "double_tap_toast_count";
@@ -1353,17 +1349,28 @@ public class WebSettings {
if (DebugFlags.WEB_SETTINGS) {
junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
}
- sGoogleLocationSettingManager = new GoogleLocationSettingManager(mContext);
- sGoogleLocationSettingManager.start();
+
+ GoogleLocationSettingManager.getInstance().start(mContext);
+
SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
Context.MODE_PRIVATE);
- mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
- mDoubleTapToastCount);
+ if (mDoubleTapToastCount > 0) {
+ mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
+ mDoubleTapToastCount);
+ }
nativeSync(frame.mNativeFrame);
mSyncPending = false;
mEventHandler.createHandler();
}
+ /**
+ * Let the Settings object know that our owner is being destroyed.
+ */
+ /*package*/
+ synchronized void onDestroyed() {
+ GoogleLocationSettingManager.getInstance().stop();
+ }
+
private int pin(int size) {
// FIXME: 72 is just an arbitrary max text size value.
if (size < 1) {
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index ae560fb..0022248 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -20,9 +20,8 @@ import android.os.Handler;
import android.os.Message;
import android.util.Log;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.Collection;
+import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -51,28 +50,41 @@ public final class WebStorage {
// Global instance of a WebStorage
private static WebStorage sWebStorage;
- // We keep the origins, quotas and usages as member values
- // that we protect via a lock and update in syncValues().
- // This is needed to transfer this data across threads.
- private static Lock mLock = new ReentrantLock();
- private static Condition mUpdateCondition = mLock.newCondition();
- private static boolean mUpdateAvailable;
-
// Message ids
static final int UPDATE = 0;
static final int SET_QUOTA_ORIGIN = 1;
static final int DELETE_ORIGIN = 2;
static final int DELETE_ALL = 3;
+ static final int GET_ORIGINS = 4;
+ static final int GET_USAGE_ORIGIN = 5;
+ static final int GET_QUOTA_ORIGIN = 6;
+
+ // Message ids on the UI thread
+ static final int RETURN_ORIGINS = 0;
+ static final int RETURN_USAGE_ORIGIN = 1;
+ static final int RETURN_QUOTA_ORIGIN = 2;
+
+ private static final String ORIGINS = "origins";
+ private static final String ORIGIN = "origin";
+ private static final String CALLBACK = "callback";
+ private static final String USAGE = "usage";
+ private static final String QUOTA = "quota";
- private Set <String> mOrigins;
- private HashMap <String, Long> mQuotas = new HashMap<String, Long>();
- private HashMap <String, Long> mUsages = new HashMap<String, Long>();
+ private Map <String, Origin> mOrigins;
private Handler mHandler = null;
+ private Handler mUIHandler = null;
- private static class Origin {
+ static class Origin {
String mOrigin = null;
long mQuota = 0;
+ long mUsage = 0;
+
+ public Origin(String origin, long quota, long usage) {
+ mOrigin = origin;
+ mQuota = quota;
+ mUsage = usage;
+ }
public Origin(String origin, long quota) {
mOrigin = origin;
@@ -90,11 +102,49 @@ public final class WebStorage {
public long getQuota() {
return mQuota;
}
+
+ public long getUsage() {
+ return mUsage;
+ }
+ }
+
+ /**
+ * @hide
+ * Message handler, UI side
+ */
+ public void createUIHandler() {
+ if (mUIHandler == null) {
+ mUIHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case RETURN_ORIGINS: {
+ Map values = (Map) msg.obj;
+ Map origins = (Map) values.get(ORIGINS);
+ ValueCallback<Map> callback = (ValueCallback<Map>) values.get(CALLBACK);
+ callback.onReceiveValue(origins);
+ } break;
+
+ case RETURN_USAGE_ORIGIN: {
+ Map values = (Map) msg.obj;
+ ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK);
+ callback.onReceiveValue((Long)values.get(USAGE));
+ } break;
+
+ case RETURN_QUOTA_ORIGIN: {
+ Map values = (Map) msg.obj;
+ ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK);
+ callback.onReceiveValue((Long)values.get(QUOTA));
+ } break;
+ }
+ }
+ };
+ }
}
/**
* @hide
- * Message handler
+ * Message handler, webcore side
*/
public void createHandler() {
if (mHandler == null) {
@@ -117,6 +167,46 @@ public final class WebStorage {
nativeDeleteAllData();
break;
+ case GET_ORIGINS: {
+ syncValues();
+ ValueCallback callback = (ValueCallback) msg.obj;
+ Map origins = new HashMap(mOrigins);
+ Map values = new HashMap<String, Object>();
+ values.put(CALLBACK, callback);
+ values.put(ORIGINS, origins);
+ postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
+ } break;
+
+ case GET_USAGE_ORIGIN: {
+ syncValues();
+ Map values = (Map) msg.obj;
+ String origin = (String) values.get(ORIGIN);
+ ValueCallback callback = (ValueCallback) values.get(CALLBACK);
+ Origin website = mOrigins.get(origin);
+ Map retValues = new HashMap<String, Object>();
+ retValues.put(CALLBACK, callback);
+ if (website != null) {
+ long usage = website.getUsage();
+ retValues.put(USAGE, new Long(usage));
+ }
+ postUIMessage(Message.obtain(null, RETURN_USAGE_ORIGIN, retValues));
+ } break;
+
+ case GET_QUOTA_ORIGIN: {
+ syncValues();
+ Map values = (Map) msg.obj;
+ String origin = (String) values.get(ORIGIN);
+ ValueCallback callback = (ValueCallback) values.get(CALLBACK);
+ Origin website = mOrigins.get(origin);
+ Map retValues = new HashMap<String, Object>();
+ retValues.put(CALLBACK, callback);
+ if (website != null) {
+ long quota = website.getQuota();
+ retValues.put(QUOTA, new Long(quota));
+ }
+ postUIMessage(Message.obtain(null, RETURN_QUOTA_ORIGIN, retValues));
+ } break;
+
case UPDATE:
syncValues();
break;
@@ -126,82 +216,91 @@ public final class WebStorage {
}
}
+ /*
+ * When calling getOrigins(), getUsageForOrigin() and getQuotaForOrigin(),
+ * we need to get the values from webcore, but we cannot block while doing so
+ * as we used to do, as this could result in a full deadlock (other webcore
+ * messages received while we are still blocked here, see http://b/2127737).
+ *
+ * We have to do everything asynchronously, by providing a callback function.
+ * We post a message on the webcore thread (mHandler) that will get the result
+ * from webcore, and we post it back on the UI thread (using mUIHandler).
+ * We can then use the callback function to return the value.
+ */
+
/**
* @hide
* Returns a list of origins having a database
*/
- public Set getOrigins() {
- Set ret = null;
- mLock.lock();
- try {
- mUpdateAvailable = false;
- update();
- while (!mUpdateAvailable) {
- mUpdateCondition.await();
+ public void getOrigins(ValueCallback<Map> callback) {
+ if (callback != null) {
+ if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+ syncValues();
+ callback.onReceiveValue(mOrigins);
+ } else {
+ postMessage(Message.obtain(null, GET_ORIGINS, callback));
}
- ret = mOrigins;
- } catch (InterruptedException e) {
- Log.e(TAG, "Exception while waiting on the updated origins", e);
- } finally {
- mLock.unlock();
}
- return ret;
+ }
+
+ /**
+ * Returns a list of origins having a database
+ * should only be called from WebViewCore.
+ */
+ Collection<Origin> getOriginsSync() {
+ if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+ update();
+ return mOrigins.values();
+ }
+ return null;
}
/**
* @hide
* Returns the use for a given origin
*/
- public long getUsageForOrigin(String origin) {
- long ret = 0;
+ public void getUsageForOrigin(String origin, ValueCallback<Long> callback) {
+ if (callback == null) {
+ return;
+ }
if (origin == null) {
- return ret;
+ callback.onReceiveValue(null);
+ return;
}
- mLock.lock();
- try {
- mUpdateAvailable = false;
- update();
- while (!mUpdateAvailable) {
- mUpdateCondition.await();
- }
- Long usage = mUsages.get(origin);
- if (usage != null) {
- ret = usage.longValue();
- }
- } catch (InterruptedException e) {
- Log.e(TAG, "Exception while waiting on the updated origins", e);
- } finally {
- mLock.unlock();
+ if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+ syncValues();
+ Origin website = mOrigins.get(origin);
+ callback.onReceiveValue(new Long(website.getUsage()));
+ } else {
+ HashMap values = new HashMap<String, Object>();
+ values.put(ORIGIN, origin);
+ values.put(CALLBACK, callback);
+ postMessage(Message.obtain(null, GET_USAGE_ORIGIN, values));
}
- return ret;
}
/**
* @hide
* Returns the quota for a given origin
*/
- public long getQuotaForOrigin(String origin) {
- long ret = 0;
+ public void getQuotaForOrigin(String origin, ValueCallback<Long> callback) {
+ if (callback == null) {
+ return;
+ }
if (origin == null) {
- return ret;
+ callback.onReceiveValue(null);
+ return;
}
- mLock.lock();
- try {
- mUpdateAvailable = false;
- update();
- while (!mUpdateAvailable) {
- mUpdateCondition.await();
- }
- Long quota = mQuotas.get(origin);
- if (quota != null) {
- ret = quota.longValue();
- }
- } catch (InterruptedException e) {
- Log.e(TAG, "Exception while waiting on the updated origins", e);
- } finally {
- mLock.unlock();
+ if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+ syncValues();
+ Origin website = mOrigins.get(origin);
+ callback.onReceiveValue(new Long(website.getUsage()));
+ } else {
+ HashMap values = new HashMap<String, Object>();
+ values.put(ORIGIN, origin);
+ values.put(CALLBACK, callback);
+ postMessage(Message.obtain(null, GET_QUOTA_ORIGIN, values));
}
- return ret;
}
/**
@@ -256,6 +355,15 @@ public final class WebStorage {
}
/**
+ * Utility function to send a message to the handler on the UI thread
+ */
+ private void postUIMessage(Message msg) {
+ if (mUIHandler != null) {
+ mUIHandler.sendMessage(msg);
+ }
+ }
+
+ /**
* @hide
* Get the global instance of WebStorage.
* @return A single instance of WebStorage.
@@ -284,21 +392,14 @@ public final class WebStorage {
* set the local values with the current ones
*/
private void syncValues() {
- mLock.lock();
- Set tmp = nativeGetOrigins();
- mOrigins = new HashSet<String>();
- mQuotas.clear();
- mUsages.clear();
- Iterator<String> iter = tmp.iterator();
- while (iter.hasNext()) {
- String origin = iter.next();
- mOrigins.add(origin);
- mQuotas.put(origin, new Long(nativeGetQuotaForOrigin(origin)));
- mUsages.put(origin, new Long(nativeGetUsageForOrigin(origin)));
+ Set<String> tmp = nativeGetOrigins();
+ mOrigins = new HashMap<String, Origin>();
+ for (String origin : tmp) {
+ Origin website = new Origin(origin,
+ nativeGetUsageForOrigin(origin),
+ nativeGetQuotaForOrigin(origin));
+ mOrigins.put(origin, website);
}
- mUpdateAvailable = true;
- mUpdateCondition.signal();
- mLock.unlock();
}
// Native functions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 113eac5..51c5e1f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3772,10 +3772,10 @@ public class WebView extends AbsoluteLayout
mZoomButtonsController.setVisible(true);
int count = settings.getDoubleTapToastCount();
if (mInZoomOverview && count > 0) {
- settings.setDoubleTapToastCount(count--);
+ settings.setDoubleTapToastCount(--count);
Toast.makeText(mContext,
com.android.internal.R.string.double_tap_toast,
- Toast.LENGTH_SHORT).show();
+ Toast.LENGTH_LONG).show();
}
}
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index e734444..ce45373 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -17,6 +17,7 @@
package android.webkit;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.DrawFilter;
import android.graphics.Paint;
@@ -37,6 +38,7 @@ import android.view.SurfaceView;
import android.view.View;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Map;
import java.util.Set;
@@ -162,8 +164,10 @@ final class WebViewCore {
// The WebIconDatabase needs to be initialized within the UI thread so
// just request the instance here.
WebIconDatabase.getInstance();
- // Create the WebStorage singleton
- WebStorage.getInstance();
+ // Create the WebStorage singleton and the UI handler
+ WebStorage.getInstance().createUIHandler();
+ // Create the UI handler for GeolocationPermissions
+ GeolocationPermissions.getInstance().createUIHandler();
// Send a message to initialize the WebViewCore.
Message init = sWebCoreHandler.obtainMessage(
WebCoreThread.INITIALIZE, this);
@@ -850,6 +854,7 @@ final class WebViewCore {
synchronized (WebViewCore.this) {
mBrowserFrame.destroy();
mBrowserFrame = null;
+ mSettings.onDestroyed();
mNativeClass = 0;
}
break;
@@ -1519,13 +1524,14 @@ final class WebViewCore {
// callbacks. Computes the sum of database quota for all origins.
private long getUsedQuota() {
WebStorage webStorage = WebStorage.getInstance();
- Set<String> origins = webStorage.getOrigins();
+ Collection<WebStorage.Origin> origins = webStorage.getOriginsSync();
+
if (origins == null) {
return 0;
}
long usedQuota = 0;
- for (String origin : origins) {
- usedQuota += webStorage.getQuotaForOrigin(origin);
+ for (WebStorage.Origin website : origins) {
+ usedQuota += website.getQuota();
}
return usedQuota;
}
@@ -2086,22 +2092,49 @@ final class WebViewCore {
}
}
- // PluginWidget functions for creating SurfaceViews for the Surface drawing
- // model.
- private ViewManager.ChildView createSurface(String packageName, String className,
+ // called by JNI. PluginWidget function to launch an activity and overlays
+ // the activity with the View provided by the plugin class.
+ private void startFullScreenPluginActivity(String libName, String clsName, int npp) {
+ if (mWebView == null) {
+ return;
+ }
+
+ String pkgName = PluginManager.getInstance(null).getPluginsAPKName(libName);
+ if (pkgName == null) {
+ Log.w(LOGTAG, "Unable to resolve " + libName + " to a plugin APK");
+ return;
+ }
+
+ Intent intent = new Intent("android.intent.webkit.PLUGIN");
+ intent.putExtra(PluginActivity.INTENT_EXTRA_PACKAGE_NAME, pkgName);
+ intent.putExtra(PluginActivity.INTENT_EXTRA_CLASS_NAME, clsName);
+ intent.putExtra(PluginActivity.INTENT_EXTRA_NPP_INSTANCE, npp);
+ mWebView.getContext().startActivity(intent);
+ }
+
+ // called by JNI. PluginWidget functions for creating an embedded View for
+ // the surface drawing model.
+ private ViewManager.ChildView createSurface(String libName, String clsName,
int npp, int x, int y, int width, int height) {
if (mWebView == null) {
return null;
}
- PluginStub stub = PluginUtil.getPluginStub(mWebView.getContext(), packageName, className);
+
+ String pkgName = PluginManager.getInstance(null).getPluginsAPKName(libName);
+ if (pkgName == null) {
+ Log.w(LOGTAG, "Unable to resolve " + libName + " to a plugin APK");
+ return null;
+ }
+
+ PluginStub stub =PluginUtil.getPluginStub(mWebView.getContext(),pkgName, clsName);
if (stub == null) {
- Log.e(LOGTAG, "Unable to find plugin class (" + className +
- ") in the apk (" + packageName + ")");
+ Log.e(LOGTAG, "Unable to find plugin class (" + clsName +
+ ") in the apk (" + pkgName + ")");
return null;
}
-
+
View pluginView = stub.getEmbeddedView(npp, mWebView.getContext());
-
+
ViewManager.ChildView view = mWebView.mViewManager.createView();
view.mView = pluginView;
view.attachView(x, y, width, height);
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 703cd8e..31c7814 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -743,7 +743,7 @@ public class ScrollView extends FrameLayout {
final int maxJump = getMaxScrollAmount();
- if (nextFocused != null && isWithinDeltaOfScreen(nextFocused, maxJump)) {
+ if (nextFocused != null && isWithinDeltaOfScreen(nextFocused, maxJump, getHeight())) {
nextFocused.getDrawingRect(mTempRect);
offsetDescendantRectToMyCoords(nextFocused, mTempRect);
int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
@@ -792,19 +792,19 @@ public class ScrollView extends FrameLayout {
* screen.
*/
private boolean isOffScreen(View descendant) {
- return !isWithinDeltaOfScreen(descendant, 0);
+ return !isWithinDeltaOfScreen(descendant, 0, getHeight());
}
/**
* @return whether the descendant of this scroll view is within delta
* pixels of being on the screen.
*/
- private boolean isWithinDeltaOfScreen(View descendant, int delta) {
+ private boolean isWithinDeltaOfScreen(View descendant, int delta, int height) {
descendant.getDrawingRect(mTempRect);
offsetDescendantRectToMyCoords(descendant, mTempRect);
return (mTempRect.bottom + delta) >= getScrollY()
- && (mTempRect.top - delta) <= (getScrollY() + getHeight());
+ && (mTempRect.top - delta) <= (getScrollY() + height);
}
/**
@@ -1124,9 +1124,10 @@ public class ScrollView extends FrameLayout {
if (null == currentFocused || this == currentFocused)
return;
- final int maxJump = mBottom - mTop;
-
- if (isWithinDeltaOfScreen(currentFocused, maxJump)) {
+ // If the currently-focused view was visible on the screen when the
+ // screen was at the old height, then scroll the screen to make that
+ // view visible with the new screen height.
+ if (isWithinDeltaOfScreen(currentFocused, 0, oldh)) {
currentFocused.getDrawingRect(mTempRect);
offsetDescendantRectToMyCoords(currentFocused, mTempRect);
int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2e3364b..3c61c1c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2874,26 +2874,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_inputType
*/
public void setInputType(int type) {
+ final boolean wasPassword = isPasswordInputType(mInputType);
+ final boolean wasVisiblePassword = isVisiblePasswordInputType(mInputType);
setInputType(type, false);
- final int variation = type&(EditorInfo.TYPE_MASK_CLASS
- |EditorInfo.TYPE_MASK_VARIATION);
- final boolean isPassword = variation
- == (EditorInfo.TYPE_CLASS_TEXT
- |EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
+ final boolean isPassword = isPasswordInputType(type);
+ final boolean isVisiblePassword = isVisiblePasswordInputType(type);
boolean forceUpdate = false;
if (isPassword) {
setTransformationMethod(PasswordTransformationMethod.getInstance());
setTypefaceByIndex(MONOSPACE, 0);
- } else if (mTransformation == PasswordTransformationMethod.getInstance()) {
- // We need to clean up if we were previously in password mode.
- if (variation != (EditorInfo.TYPE_CLASS_TEXT
- |EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)) {
- setTypefaceByIndex(-1, -1);
- }
- forceUpdate = true;
- } else if (variation == (EditorInfo.TYPE_CLASS_TEXT
- |EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)) {
+ } else if (isVisiblePassword) {
setTypefaceByIndex(MONOSPACE, 0);
+ } else if (wasPassword || wasVisiblePassword) {
+ // not in password mode, clean up typeface and transformation
+ setTypefaceByIndex(-1, -1);
+ if (mTransformation == PasswordTransformationMethod.getInstance()) {
+ forceUpdate = true;
+ }
}
boolean multiLine = (type&(EditorInfo.TYPE_MASK_CLASS
@@ -2913,6 +2910,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (imm != null) imm.restartInput(this);
}
+ private boolean isPasswordInputType(int inputType) {
+ final int variation = inputType & (EditorInfo.TYPE_MASK_CLASS
+ | EditorInfo.TYPE_MASK_VARIATION);
+ return variation
+ == (EditorInfo.TYPE_CLASS_TEXT
+ | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
+ }
+
+ private boolean isVisiblePasswordInputType(int inputType) {
+ final int variation = inputType & (EditorInfo.TYPE_MASK_CLASS
+ | EditorInfo.TYPE_MASK_VARIATION);
+ return variation
+ == (EditorInfo.TYPE_CLASS_TEXT
+ | EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
+ }
+
/**
* Directly change the content type integer of the text view, without
* modifying any other state.
diff --git a/core/java/com/android/internal/widget/RotarySelector.java b/core/java/com/android/internal/widget/RotarySelector.java
index f610211..426cef5 100644
--- a/core/java/com/android/internal/widget/RotarySelector.java
+++ b/core/java/com/android/internal/widget/RotarySelector.java
@@ -25,8 +25,9 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
-import android.view.SoundEffectConstants;
-import android.view.animation.AccelerateInterpolator;
+import android.view.VelocityTracker;
+import android.view.ViewConfiguration;
+import android.view.animation.DecelerateInterpolator;
import static android.view.animation.AnimationUtils.currentAnimationTimeMillis;
import com.android.internal.R;
@@ -60,16 +61,18 @@ public class RotarySelector extends View {
private int mLeftHandleX;
private int mRightHandleX;
- // current offset of user's dragging
- private int mTouchDragOffset = 0;
+ // current offset of rotary widget along the x axis
+ private int mRotaryOffsetX = 0;
// state of the animation used to bring the handle back to its start position when
// the user lets go before triggering an action
private boolean mAnimating = false;
- private long mAnimationStartTime; // set to the end point of the animatino
+ private long mAnimationStartTime;
private long mAnimationDuration;
- private int mAnimatingDeltaXStart; // the animation will interpolate from this delta down to zero
- private AccelerateInterpolator mInterpolator;
+ private int mAnimatingDeltaXStart; // the animation will interpolate from this delta to zero
+ private int mAnimatingDeltaXEnd;
+
+ private DecelerateInterpolator mInterpolator;
/**
* If the user is currently dragging something.
@@ -87,8 +90,8 @@ public class RotarySelector extends View {
// Vibration (haptic feedback)
private Vibrator mVibrator;
- private static final long VIBRATE_SHORT = 60; // msec
- private static final long VIBRATE_LONG = 100; // msec
+ private static final long VIBRATE_SHORT = 30; // msec
+ private static final long VIBRATE_LONG = 60; // msec
/**
* The drawable for the arrows need to be scrunched this many dips towards the rotary bg below
@@ -114,11 +117,27 @@ public class RotarySelector extends View {
static final int SNAP_BACK_ANIMATION_DURATION_MILLIS = 300;
static final int SPIN_ANIMATION_DURATION_MILLIS = 800;
- private static final boolean DRAW_CENTER_DIMPLE = false;
+ private static final boolean DRAW_CENTER_DIMPLE = true;
private int mEdgeTriggerThresh;
private int mDimpleWidth;
private int mBackgroundWidth;
private int mBackgroundHeight;
+ private final int mOuterRadius;
+ private final int mInnerRadius;
+ private int mDimpleSpacing;
+
+ private VelocityTracker mVelocityTracker;
+ private int mMinimumVelocity;
+ private int mMaximumVelocity;
+
+ /**
+ * The number of dimples we are flinging when we do the "spin" animation. Used to know when to
+ * wrap the icons back around so they "rotate back" onto the screen.
+ * @see #updateAnimation()
+ */
+ private int mDimplesOfFling = 0;
+
+
public RotarySelector(Context context) {
this(context, null);
@@ -152,7 +171,7 @@ public class RotarySelector extends View {
mArrowLongLeft.setBounds(0, 0, arrowW, arrowH);
mArrowLongRight.setBounds(0, 0, arrowW, arrowH);
- mInterpolator = new AccelerateInterpolator();
+ mInterpolator = new DecelerateInterpolator(1f);
mEdgeTriggerThresh = (int) (mDensity * EDGE_TRIGGER_DIP);
@@ -160,6 +179,23 @@ public class RotarySelector extends View {
mBackgroundWidth = mBackground.getIntrinsicWidth();
mBackgroundHeight = mBackground.getIntrinsicHeight();
+ mOuterRadius = (int) (mDensity * OUTER_ROTARY_RADIUS_DIP);
+ mInnerRadius = (int) ((OUTER_ROTARY_RADIUS_DIP - ROTARY_STROKE_WIDTH_DIP) * mDensity);
+
+ final ViewConfiguration configuration = ViewConfiguration.get(mContext);
+ mMinimumVelocity = configuration.getScaledMinimumFlingVelocity() * 2;
+ mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mLeftHandleX = (int) (EDGE_PADDING_DIP * mDensity) + mDimpleWidth / 2;
+ mRightHandleX =
+ getWidth() - (int) (EDGE_PADDING_DIP * mDensity) - mDimpleWidth / 2;
+
+ mDimpleSpacing = (getWidth() / 2) - mLeftHandleX;
}
/**
@@ -229,43 +265,21 @@ public class RotarySelector extends View {
setMeasuredDimension(width, backgroundH + arrowH - arrowScrunch);
}
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- mLeftHandleX = (int) (EDGE_PADDING_DIP * mDensity) + mDimpleWidth / 2;
- mRightHandleX =
- getWidth() - (int) (EDGE_PADDING_DIP * mDensity) - mDimpleWidth / 2;
- }
-
// private Paint mPaint = new Paint();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (DBG) {
- log(String.format("onDraw: mAnimating=%s, mTouchDragOffset=%d, mGrabbedState=%d",
- mAnimating, mTouchDragOffset, mGrabbedState));
+ log(String.format("onDraw: mAnimating=%s, mRotaryOffsetX=%d, mGrabbedState=%d",
+ mAnimating, mRotaryOffsetX, mGrabbedState));
}
final int height = getHeight();
// update animating state before we draw anything
if (mAnimating) {
- final long millisSoFar = currentAnimationTimeMillis() - mAnimationStartTime;
- final long millisLeft = mAnimationDuration - millisSoFar;
- if (DBG) log("millisleft for animating: " + millisLeft);
- if (millisLeft <= 0) {
- reset();
- } else {
- // we always use the snap back duration as the denominator for interpolation
- // to get a consistent velocity (bascially this makes us happy for the snap back
- // and the spin around one).
- final long denom = SNAP_BACK_ANIMATION_DURATION_MILLIS; // mAnimationDuration
- float interpolation = mInterpolator.getInterpolation(
- (float) millisLeft / denom);
- mTouchDragOffset = (int) (mAnimatingDeltaXStart * interpolation);
- }
+ updateAnimation();
}
// Background:
@@ -302,16 +316,13 @@ public class RotarySelector extends View {
// float or = OUTER_ROTARY_RADIUS_DIP * mDensity;
// canvas.drawCircle(getWidth() / 2, or + mBackground.getBounds().top, or, mPaint);
- final int outerRadius = (int) (mDensity * OUTER_ROTARY_RADIUS_DIP);
- final int innerRadius =
- (int) ((OUTER_ROTARY_RADIUS_DIP - ROTARY_STROKE_WIDTH_DIP) * mDensity);
final int bgTop = mBackground.getBounds().top;
{
- final int xOffset = mLeftHandleX + mTouchDragOffset;
+ final int xOffset = mLeftHandleX + mRotaryOffsetX;
final int drawableY = getYOnArc(
mBackground,
- innerRadius,
- outerRadius,
+ mInnerRadius,
+ mOuterRadius,
xOffset);
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
@@ -321,22 +332,22 @@ public class RotarySelector extends View {
}
if (DRAW_CENTER_DIMPLE) {
- final int xOffset = getWidth() / 2 + mTouchDragOffset;
+ final int xOffset = getWidth() / 2 + mRotaryOffsetX;
final int drawableY = getYOnArc(
mBackground,
- innerRadius,
- outerRadius,
+ mInnerRadius,
+ mOuterRadius,
xOffset);
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
}
{
- final int xOffset = mRightHandleX + mTouchDragOffset;
+ final int xOffset = mRightHandleX + mRotaryOffsetX;
final int drawableY = getYOnArc(
mBackground,
- innerRadius,
- outerRadius,
+ mInnerRadius,
+ mOuterRadius,
xOffset);
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
@@ -345,7 +356,33 @@ public class RotarySelector extends View {
}
}
- if (mAnimating) invalidate();
+ // draw extra left hand dimples
+ int dimpleLeft = mRotaryOffsetX + mLeftHandleX - mDimpleSpacing;
+ final int halfdimple = mDimpleWidth / 2;
+ while (dimpleLeft > -halfdimple) {
+ final int drawableY = getYOnArc(
+ mBackground,
+ mInnerRadius,
+ mOuterRadius,
+ dimpleLeft);
+
+ drawCentered(mDimple, canvas, dimpleLeft, drawableY + bgTop);
+ dimpleLeft -= mDimpleSpacing;
+ }
+
+ // draw extra right hand dimples
+ int dimpleRight = mRotaryOffsetX + mRightHandleX + mDimpleSpacing;
+ final int rightThresh = mRight + halfdimple;
+ while (dimpleRight < rightThresh) {
+ final int drawableY = getYOnArc(
+ mBackground,
+ mInnerRadius,
+ mOuterRadius,
+ dimpleRight);
+
+ drawCentered(mDimple, canvas, dimpleRight, drawableY + bgTop);
+ dimpleRight += mDimpleSpacing;
+ }
}
/**
@@ -395,6 +432,11 @@ public class RotarySelector extends View {
if (mAnimating) {
return true;
}
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(event);
+
final int eventX = (int) event.getX();
final int hitWindow = mDimpleWidth;
@@ -409,12 +451,12 @@ public class RotarySelector extends View {
invalidate();
}
if (eventX < mLeftHandleX + hitWindow) {
- mTouchDragOffset = eventX - mLeftHandleX;
+ mRotaryOffsetX = eventX - mLeftHandleX;
mGrabbedState = LEFT_HANDLE_GRABBED;
invalidate();
vibrate(VIBRATE_SHORT);
} else if (eventX > mRightHandleX - hitWindow) {
- mTouchDragOffset = eventX - mRightHandleX;
+ mRotaryOffsetX = eventX - mRightHandleX;
mGrabbedState = RIGHT_HANDLE_GRABBED;
invalidate();
vibrate(VIBRATE_SHORT);
@@ -424,35 +466,38 @@ public class RotarySelector extends View {
case MotionEvent.ACTION_MOVE:
if (DBG) log("touch-move");
if (mGrabbedState == LEFT_HANDLE_GRABBED) {
- mTouchDragOffset = eventX - mLeftHandleX;
+ mRotaryOffsetX = eventX - mLeftHandleX;
invalidate();
if (eventX >= getRight() - mEdgeTriggerThresh && !mTriggered) {
mTriggered = true;
dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
- // set up "spin around animation"
- mAnimating = true;
- mAnimationStartTime = currentAnimationTimeMillis();
- mAnimationDuration = SPIN_ANIMATION_DURATION_MILLIS;
- mAnimatingDeltaXStart = -mBackgroundWidth*3;
- mTouchDragOffset = 0;
- mGrabbedState = NOTHING_GRABBED;
- invalidate();
-
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ final int velocity = Math.max(mMinimumVelocity, (int) velocityTracker.getXVelocity());
+ mDimplesOfFling = Math.max(
+ 8,
+ Math.abs(velocity / mDimpleSpacing));
+ startAnimationWithVelocity(
+ eventX - mLeftHandleX,
+ mDimplesOfFling * mDimpleSpacing,
+ velocity);
}
} else if (mGrabbedState == RIGHT_HANDLE_GRABBED) {
- mTouchDragOffset = eventX - mRightHandleX;
+ mRotaryOffsetX = eventX - mRightHandleX;
invalidate();
if (eventX <= mEdgeTriggerThresh && !mTriggered) {
mTriggered = true;
dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
- // set up "spin around animation"
- mAnimating = true;
- mAnimationStartTime = currentAnimationTimeMillis();
- mAnimationDuration = SPIN_ANIMATION_DURATION_MILLIS;
- mAnimatingDeltaXStart = mBackgroundWidth*3;
- mTouchDragOffset = 0;
- mGrabbedState = NOTHING_GRABBED;
- invalidate();
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ final int velocity = Math.min(-mMinimumVelocity, (int) velocityTracker.getXVelocity());
+ mDimplesOfFling = Math.max(
+ 8,
+ Math.abs(velocity / mDimpleSpacing));
+ startAnimationWithVelocity(
+ eventX - mRightHandleX,
+ -(mDimplesOfFling * mDimpleSpacing),
+ velocity);
}
}
break;
@@ -462,35 +507,84 @@ public class RotarySelector extends View {
if (mGrabbedState == LEFT_HANDLE_GRABBED
&& Math.abs(eventX - mLeftHandleX) > 5) {
// set up "snap back" animation
- mAnimating = true;
- mAnimationStartTime = currentAnimationTimeMillis();
- mAnimationDuration = SNAP_BACK_ANIMATION_DURATION_MILLIS;
- mAnimatingDeltaXStart = eventX - mLeftHandleX;
+ startAnimation(eventX - mLeftHandleX, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
} else if (mGrabbedState == RIGHT_HANDLE_GRABBED
&& Math.abs(eventX - mRightHandleX) > 5) {
// set up "snap back" animation
- mAnimating = true;
- mAnimationStartTime = currentAnimationTimeMillis();
- mAnimationDuration = SNAP_BACK_ANIMATION_DURATION_MILLIS;
- mAnimatingDeltaXStart = eventX - mRightHandleX;
+ startAnimation(eventX - mRightHandleX, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
}
-
- mTouchDragOffset = 0;
+ mRotaryOffsetX = 0;
mGrabbedState = NOTHING_GRABBED;
invalidate();
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle(); // wishin' we had generational GC
+ mVelocityTracker = null;
+ }
break;
case MotionEvent.ACTION_CANCEL:
if (DBG) log("touch-cancel");
reset();
invalidate();
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
break;
}
return true;
}
+ private void startAnimation(int startX, int endX, int duration) {
+ mAnimating = true;
+ mAnimationStartTime = currentAnimationTimeMillis();
+ mAnimationDuration = duration;
+ mAnimatingDeltaXStart = startX;
+ mAnimatingDeltaXEnd = endX;
+ mGrabbedState = NOTHING_GRABBED;
+ mDimplesOfFling = 0;
+ invalidate();
+ }
+
+ private void startAnimationWithVelocity(int startX, int endX, int pixelsPerSecond) {
+ mAnimating = true;
+ mAnimationStartTime = currentAnimationTimeMillis();
+ mAnimationDuration = 1000 * (endX - startX) / pixelsPerSecond;
+ mAnimatingDeltaXStart = startX;
+ mAnimatingDeltaXEnd = endX;
+ mGrabbedState = NOTHING_GRABBED;
+ invalidate();
+ }
+
+ private void updateAnimation() {
+ final long millisSoFar = currentAnimationTimeMillis() - mAnimationStartTime;
+ final long millisLeft = mAnimationDuration - millisSoFar;
+ final int totalDeltaX = mAnimatingDeltaXStart - mAnimatingDeltaXEnd;
+ if (DBG) log("millisleft for animating: " + millisLeft);
+ if (millisLeft <= 0) {
+ reset();
+ return;
+ }
+ // from 0 to 1 as animation progresses
+ float interpolation =
+ mInterpolator.getInterpolation((float) millisSoFar / mAnimationDuration);
+ final int dx = (int) (totalDeltaX * (1 - interpolation));
+ mRotaryOffsetX = mAnimatingDeltaXEnd + dx;
+ if (mDimplesOfFling > 0) {
+ if (mRotaryOffsetX < 4 * mDimpleSpacing) {
+ // wrap around on fling left
+ mRotaryOffsetX += (4 + mDimplesOfFling - 4) * mDimpleSpacing;
+ } else if (mRotaryOffsetX > 4 * mDimpleSpacing) {
+ // wrap around on fling right
+ mRotaryOffsetX -= (4 + mDimplesOfFling - 4) * mDimpleSpacing;
+ }
+ }
+ invalidate();
+ }
+
private void reset() {
mAnimating = false;
- mTouchDragOffset = 0;
+ mRotaryOffsetX = 0;
+ mDimplesOfFling = 0;
mGrabbedState = NOTHING_GRABBED;
mTriggered = false;
}
@@ -500,7 +594,8 @@ public class RotarySelector extends View {
*/
private synchronized void vibrate(long duration) {
if (mVibrator == null) {
- mVibrator = (android.os.Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ mVibrator = (android.os.Vibrator)
+ getContext().getSystemService(Context.VIBRATOR_SERVICE);
}
mVibrator.vibrate(duration);
}
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 04f6e07..3e4c9af 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -112,8 +112,8 @@ bool Context::runRootScript()
#endif
rsAssert(mRootScript->mEnviroment.mIsRoot);
- //glColor4f(1,1,1,1);
- //glEnable(GL_LIGHT0);
+ eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
+ eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
glViewport(0, 0, mEGL.mWidth, mEGL.mHeight);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_POINT_SMOOTH);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
index 0401390..53afb1d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
@@ -32,6 +32,29 @@ public class MediaProfileReader {
return s;
}
+ public static boolean getWMAEnable() {
+ // push all the property into one big table
+ int wmaEnable = 1;
+ wmaEnable = SystemProperties.getInt("ro.media.dec.aud.wma.enabled",
+ wmaEnable);
+ if (wmaEnable == 1) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static boolean getWMVEnable(){
+ int wmvEnable = 1;
+ wmvEnable = SystemProperties.getInt("ro.media.dec.vid.wmv.enabled",
+ wmvEnable);
+ if (wmvEnable == 1) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
public static void createVideoProfileTable() {
// push all the property into one big table
String encoderType = getVideoCodecProperty();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
index 30e2d6c..392d1d5 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
@@ -18,6 +18,7 @@ package com.android.mediaframeworktest.functional;
import com.android.mediaframeworktest.MediaFrameworkTest;
import com.android.mediaframeworktest.MediaNames;
+import com.android.mediaframeworktest.MediaProfileReader;
import android.content.Context;
import android.test.ActivityInstrumentationTestCase;
@@ -35,11 +36,15 @@ import java.io.File;
public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
private boolean duratoinWithinTolerence = false;
private String TAG = "MediaPlayerApiTest";
+ private boolean isWMAEnable = false;
+ private boolean isWMVEnable = false;
Context mContext;
public MediaPlayerApiTest() {
super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+ isWMAEnable = MediaProfileReader.getWMAEnable();
+ isWMVEnable = MediaProfileReader.getWMVEnable();
}
protected void setUp() throws Exception {
@@ -82,9 +87,11 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra
@MediumTest
public void testWMA9GetDuration() throws Exception {
- int duration = CodecTest.getDuration(MediaNames.WMA9);
- duratoinWithinTolerence = verifyDuration(duration, MediaNames.WMA9_LENGTH);
- assertTrue("WMA9 getDuration", duratoinWithinTolerence);
+ if (isWMAEnable) {
+ int duration = CodecTest.getDuration(MediaNames.WMA9);
+ duratoinWithinTolerence = verifyDuration(duration, MediaNames.WMA9_LENGTH);
+ assertTrue("WMA9 getDuration", duratoinWithinTolerence);
+ }
}
@MediumTest
@@ -123,8 +130,10 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra
@LargeTest
public void testWMA9GetCurrentPosition() throws Exception {
- boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.WMA9);
- assertTrue("WMA9 GetCurrentPosition", currentPosition);
+ if (isWMAEnable) {
+ boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.WMA9);
+ assertTrue("WMA9 GetCurrentPosition", currentPosition);
+ }
}
@LargeTest
@@ -160,8 +169,10 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra
@LargeTest
public void testWMA9Pause() throws Exception {
- boolean isPaused = CodecTest.pause(MediaNames.WMA9);
- assertTrue("WMA9 Pause", isPaused);
+ if (isWMAEnable) {
+ boolean isPaused = CodecTest.pause(MediaNames.WMA9);
+ assertTrue("WMA9 Pause", isPaused);
+ }
}
@LargeTest
@@ -269,8 +280,10 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra
@LargeTest
public void testWMA9SeekTo() throws Exception {
- boolean isLoop = CodecTest.seekTo(MediaNames.WMA9);
- assertTrue("WMA9 seekTo", isLoop);
+ if (isWMAEnable) {
+ boolean isLoop = CodecTest.seekTo(MediaNames.WMA9);
+ assertTrue("WMA9 seekTo", isLoop);
+ }
}
@LargeTest
@@ -309,8 +322,10 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra
@Suppress
@LargeTest
public void testWMA9SeekToEnd() throws Exception {
- boolean isEnd = CodecTest.seekToEnd(MediaNames.WMA9);
- assertTrue("WMA9 seekToEnd", isEnd);
+ if (isWMAEnable) {
+ boolean isEnd = CodecTest.seekToEnd(MediaNames.WMA9);
+ assertTrue("WMA9 seekToEnd", isEnd);
+ }
}
@LargeTest
@@ -327,8 +342,10 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra
@LargeTest
public void testWAVSeekToEnd() throws Exception {
- boolean isEnd = CodecTest.seekToEnd(MediaNames.WAV);
- assertTrue("WAV seekToEnd", isEnd);
+ if (isWMVEnable) {
+ boolean isEnd = CodecTest.seekToEnd(MediaNames.WAV);
+ assertTrue("WAV seekToEnd", isEnd);
+ }
}
@MediumTest
@@ -385,8 +402,12 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra
@LargeTest
public void testVideoWMVSeekTo() throws Exception {
- boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_WMV);
- assertTrue("WMV SeekTo", isSeek);
+ Log.v(TAG, "wmv not enable");
+ if (isWMVEnable) {
+ Log.v(TAG, "wmv enable");
+ boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_WMV);
+ assertTrue("WMV SeekTo", isSeek);
+ }
}
@LargeTest
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index b4d265d..690eff6 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -239,7 +239,7 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram
validVideo = true;
}
Log.v(TAG, "width = " + mOutputVideoWidth + " height = " + mOutputVideoHeight + " Duration = " + mOutputDuration);
- removeFile(filePath);
+ //removeFile(filePath);
return validVideo;
}
@@ -428,8 +428,9 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram
}
@LargeTest
- //est cases for the new codec
+ //test cases for the new codec
public void testDeviceSpecificCodec() throws Exception {
+ int noOfFailure = 0;
boolean recordSuccess = false;
String deviceType = MediaProfileReader.getDeviceType();
Log.v(TAG, "deviceType = " + deviceType);
@@ -450,10 +451,18 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram
} else {
recordSuccess = recordVideoWithPara(encoder[i], audio[j], "low");
}
- assertTrue((encoder[i] + audio[j]), recordSuccess);
+ if (!recordSuccess){
+ Log.v(TAG, "testDeviceSpecificCodec failed");
+ Log.v(TAG, "Encoder = " + encoder[i] + "Audio Encoder = " + audio[j]);
+ noOfFailure++;
+ }
+ //assertTrue((encoder[i] + audio[j]), recordSuccess);
}
}
}
}
+ if (noOfFailure != 0){
+ assertTrue("testDeviceSpecificCodec", false);
+ }
}
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 1dc51c8..2fa18bf 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -912,6 +912,7 @@ class BackupManagerService extends IBackupManager.Stub {
@Override
public void run() {
+ int status = BackupConstants.TRANSPORT_OK;
long startRealtime = SystemClock.elapsedRealtime();
if (DEBUG) Log.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
@@ -920,7 +921,6 @@ class BackupManagerService extends IBackupManager.Stub {
try {
EventLog.writeEvent(BACKUP_START_EVENT, mTransport.transportDirName());
- int status = BackupConstants.TRANSPORT_OK;
// If we haven't stored anything yet, we need to do an init operation.
if (status == BackupConstants.TRANSPORT_OK && mEverStoredApps.size() == 0) {
@@ -958,11 +958,6 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- // When we succeed at everything, we can remove the journal
- if (status == BackupConstants.TRANSPORT_OK && !mJournal.delete()) {
- Log.e(TAG, "Unable to remove backup journal file " + mJournal);
- }
-
if (status == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
// The backend reports that our dataset has been wiped. We need to
// reset all of our bookkeeping and instead run a new backup pass for
@@ -973,7 +968,31 @@ class BackupManagerService extends IBackupManager.Stub {
}
} catch (Exception e) {
Log.e(TAG, "Error in backup thread", e);
+ status = BackupConstants.TRANSPORT_ERROR;
} finally {
+ // If things went wrong, we need to re-stage the apps we had expected
+ // to be backing up in this pass. This journals the package names in
+ // the current active pending-backup file, not in the we are holding
+ // here in mJournal.
+ if (status != BackupConstants.TRANSPORT_OK) {
+ Log.w(TAG, "Backup pass unsuccessful, restaging");
+ for (BackupRequest req : mQueue) {
+ try {
+ dataChanged(req.appInfo.packageName);
+ } catch (RemoteException e) {
+ // can't happen; it's a local call
+ }
+ }
+ }
+
+ // Either backup was successful, in which case we of course do not need
+ // this pass's journal any more; or it failed, in which case we just
+ // re-enqueued all of these packages in the current active journal.
+ // Either way, we no longer need this pass's journal.
+ if (!mJournal.delete()) {
+ Log.e(TAG, "Unable to remove backup journal file " + mJournal);
+ }
+
// Only once we're entirely finished do we release the wakelock
mWakelock.release();
}
@@ -1219,7 +1238,7 @@ class BackupManagerService extends IBackupManager.Stub {
// build the set of apps to restore
try {
// TODO: Log this before getAvailableRestoreSets, somehow
- EventLog.writeEvent(RESTORE_START_EVENT, mTransport.transportDirName());
+ EventLog.writeEvent(RESTORE_START_EVENT, mTransport.transportDirName(), mToken);
// Get the list of all packages which have backup enabled.
// (Include the Package Manager metadata pseudo-package first.)
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 8a4b45d..a70134d 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -74,7 +74,8 @@ class DockObserver extends UEventObserver {
if (category != null) {
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(category);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
try {
mContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3c76cf2..38d2304 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -143,6 +143,7 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean DEBUG_REORDER = false;
static final boolean DEBUG_WALLPAPER = false;
static final boolean SHOW_TRANSACTIONS = false;
+ static final boolean HIDE_STACK_CRAWLS = true;
static final boolean MEASURE_LATENCY = false;
static private LatencyTimer lt;
@@ -622,7 +623,7 @@ public class WindowManagerService extends IWindowManager.Stub
private void placeWindowAfter(Object pos, WindowState window) {
final int i = mWindows.indexOf(pos);
- if (localLOGV || DEBUG_FOCUS) Log.v(
+ if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
TAG, "Adding window " + window + " at "
+ (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
mWindows.add(i+1, window);
@@ -630,7 +631,7 @@ public class WindowManagerService extends IWindowManager.Stub
private void placeWindowBefore(Object pos, WindowState window) {
final int i = mWindows.indexOf(pos);
- if (localLOGV || DEBUG_FOCUS) Log.v(
+ if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
TAG, "Adding window " + window + " at "
+ i + " of " + mWindows.size() + " (before " + pos + ")");
mWindows.add(i, window);
@@ -687,6 +688,9 @@ public class WindowManagerService extends IWindowManager.Stub
//apptoken note that the window could be a floating window
//that was created later or a window at the top of the list of
//windows associated with this token.
+ if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
+ TAG, "Adding window " + win + " at "
+ + (newIdx+1) + " of " + N);
localmWindows.add(newIdx+1, win);
}
}
@@ -766,9 +770,9 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
}
- if (localLOGV || DEBUG_FOCUS) Log.v(
- TAG, "Adding window " + win + " at "
- + i + " of " + N);
+ if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
+ TAG, "Adding window " + win + " at "
+ + i + " of " + N);
localmWindows.add(i, win);
}
}
@@ -783,9 +787,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
if (i < 0) i = 0;
- if (localLOGV || DEBUG_FOCUS) Log.v(
- TAG, "Adding window " + win + " at "
- + i + " of " + N);
+ if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
+ TAG, "Adding window " + win + " at "
+ + i + " of " + N);
localmWindows.add(i, win);
}
if (addToToken) {
@@ -955,7 +959,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (w != null) {
if (willMove) {
RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
if (DEBUG_INPUT_METHOD) Log.w(TAG, "Moving IM target from "
+ mInputMethodTarget + " to " + w, e);
mInputMethodTarget = w;
@@ -969,7 +973,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (willMove) {
RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
if (DEBUG_INPUT_METHOD) Log.w(TAG, "Moving IM target from "
+ mInputMethodTarget + " to null", e);
mInputMethodTarget = null;
@@ -982,6 +986,8 @@ public class WindowManagerService extends IWindowManager.Stub
int pos = findDesiredInputMethodWindowIndexLocked(true);
if (pos >= 0) {
win.mTargetAppToken = mInputMethodTarget.mAppToken;
+ if (DEBUG_WINDOW_MOVEMENT) Log.v(
+ TAG, "Adding input method window " + win + " at " + pos);
mWindows.add(pos, win);
moveInputMethodDialogsLocked(pos+1);
return;
@@ -1022,6 +1028,7 @@ public class WindowManagerService extends IWindowManager.Stub
int wpos = mWindows.indexOf(win);
if (wpos >= 0) {
if (wpos < interestingPos) interestingPos--;
+ if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Temp removing at " + wpos + ": " + win);
mWindows.remove(wpos);
int NC = win.mChildWindows.size();
while (NC > 0) {
@@ -1030,6 +1037,8 @@ public class WindowManagerService extends IWindowManager.Stub
int cpos = mWindows.indexOf(cw);
if (cpos >= 0) {
if (cpos < interestingPos) interestingPos--;
+ if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Temp removing child at "
+ + cpos + ": " + cw);
mWindows.remove(cpos);
}
}
@@ -1044,6 +1053,8 @@ public class WindowManagerService extends IWindowManager.Stub
// this case should be rare, so it shouldn't be that big a deal.
int wpos = mWindows.indexOf(win);
if (wpos >= 0) {
+ if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "ReAdd removing from " + wpos
+ + ": " + win);
mWindows.remove(wpos);
reAddWindowLocked(wpos, win);
}
@@ -1472,6 +1483,8 @@ public class WindowManagerService extends IWindowManager.Stub
// not in the list.
int oldIndex = localmWindows.indexOf(wallpaper);
if (oldIndex >= 0) {
+ if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Wallpaper removing at "
+ + oldIndex + ": " + wallpaper);
localmWindows.remove(oldIndex);
if (oldIndex < foundI) {
foundI--;
@@ -1479,7 +1492,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
// Now stick it in.
- if (DEBUG_WALLPAPER) Log.v(TAG, "Moving wallpaper " + wallpaper
+ if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
+ "Moving wallpaper " + wallpaper
+ " from " + oldIndex + " to " + foundI);
localmWindows.add(foundI, wallpaper);
@@ -2003,6 +2017,7 @@ public class WindowManagerService extends IWindowManager.Stub
mWindowMap.remove(win.mClient.asBinder());
mWindows.remove(win);
+ if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Final remove of window: " + win);
if (mInputMethodWindow == win) {
mInputMethodWindow = null;
@@ -2447,7 +2462,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (a != null) {
if (DEBUG_ANIM) {
RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
Log.v(TAG, "Loaded animation " + a + " for " + win, e);
}
win.setAnimation(a);
@@ -2551,7 +2566,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (a != null) {
if (DEBUG_ANIM) {
RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
Log.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
}
wtoken.setAnimation(a);
@@ -3093,6 +3108,8 @@ public class WindowManagerService extends IWindowManager.Stub
startingWindow.mToken = wtoken;
startingWindow.mRootToken = wtoken;
startingWindow.mAppToken = wtoken;
+ if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
+ "Removing starting window: " + startingWindow);
mWindows.remove(startingWindow);
ttoken.windows.remove(startingWindow);
ttoken.allAppWindows.remove(startingWindow);
@@ -3320,7 +3337,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
Log.v(TAG, "setAppVisibility(" + token + ", " + visible
+ "): mNextAppTransition=" + mNextAppTransition
+ " hidden=" + wtoken.hidden
@@ -3412,7 +3429,7 @@ public class WindowManagerService extends IWindowManager.Stub
int configChanges) {
if (DEBUG_ORIENTATION) {
RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
Log.i(TAG, "Set freezing of " + wtoken.appToken
+ ": hidden=" + wtoken.hidden + " freezing="
+ wtoken.freezingScreen, e);
@@ -3512,6 +3529,12 @@ public class WindowManagerService extends IWindowManager.Stub
if (delayed) {
// set the token aside because it has an active animation to be finished
mExitingAppTokens.add(wtoken);
+ } else {
+ // Make sure there is no animation running on this token,
+ // so any windows associated with it will be removed as
+ // soon as their animations are complete
+ wtoken.animation = null;
+ wtoken.animating = false;
}
mAppTokens.remove(wtoken);
wtoken.removed = true;
@@ -3547,7 +3570,7 @@ public class WindowManagerService extends IWindowManager.Stub
final int NW = token.windows.size();
for (int i=0; i<NW; i++) {
WindowState win = token.windows.get(i);
- if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Tmp removing window " + win);
+ if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Tmp removing app window " + win);
mWindows.remove(win);
int j = win.mChildWindows.size();
while (j > 0) {
@@ -6999,13 +7022,13 @@ public class WindowManagerService extends IWindowManager.Stub
try {
if (DEBUG_VISIBILITY) {
RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
Log.w(TAG, "Window " + this + " destroying surface "
+ mSurface + ", session " + mSession, e);
}
if (SHOW_TRANSACTIONS) {
RuntimeException ex = new RuntimeException();
- ex.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) ex.fillInStackTrace();
Log.i(TAG, " SURFACE " + mSurface + ": DESTROY ("
+ mAttrs.getTitle() + ")", ex);
}
@@ -7060,7 +7083,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean performShowLocked() {
if (DEBUG_VISIBILITY) {
RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
+ if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
Log.v(TAG, "performShow on " + this
+ ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
+ " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
@@ -8662,6 +8685,7 @@ public class WindowManagerService extends IWindowManager.Stub
final void rebuildAppWindowListLocked() {
int NW = mWindows.size();
int i;
+ int numRemoved = 0;
// First remove all existing app windows.
i=0;
@@ -8671,6 +8695,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
"Rebuild removing window: " + win);
NW--;
+ numRemoved++;
continue;
}
i++;
@@ -8691,6 +8716,11 @@ public class WindowManagerService extends IWindowManager.Stub
for (int j=0; j<NT; j++) {
i = reAddAppWindowsLocked(i, mAppTokens.get(j));
}
+
+ if (i != numRemoved) {
+ Log.w(TAG, "Rebuild removed " + numRemoved
+ + " windows but added " + i);
+ }
}
private final void assignLayersLocked() {
@@ -8853,13 +8883,34 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (!mPolicy.finishLayoutLw()) {
+ int changes = mPolicy.finishLayoutLw();
+ if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+ if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
+ assignLayersLocked();
+ }
+ }
+ if (changes == 0) {
mLayoutNeeded = false;
} else if (repeats > 2) {
Log.w(TAG, "Layout repeat aborted after too many iterations");
mLayoutNeeded = false;
+ if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
+ Configuration newConfig = updateOrientationFromAppTokensLocked(
+ null, null);
+ if (newConfig != null) {
+ mLayoutNeeded = true;
+ mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
+ }
+ }
} else {
repeats++;
+ if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
+ Configuration newConfig = updateOrientationFromAppTokensLocked(
+ null, null);
+ if (newConfig != null) {
+ mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
+ }
+ }
}
}
}
@@ -9784,6 +9835,11 @@ public class WindowManagerService extends IWindowManager.Stub
for (i=mExitingAppTokens.size()-1; i>=0; i--) {
AppWindowToken token = mExitingAppTokens.get(i);
if (!token.hasVisible && !mClosingApps.contains(token)) {
+ // Make sure there is no animation running on this token,
+ // so any windows associated with it will be removed as
+ // soon as their animations are complete
+ token.animation = null;
+ token.animating = false;
mAppTokens.remove(token);
mExitingAppTokens.remove(i);
}