diff options
87 files changed, 1968 insertions, 1396 deletions
diff --git a/api/current.xml b/api/current.xml index fde5d21..1d84c39 100644 --- a/api/current.xml +++ b/api/current.xml @@ -143602,9 +143602,97 @@ > <parameter name="path" type="java.lang.String"> </parameter> -<parameter name="state" type="java.lang.String"> +<parameter name="state" type="int"> </parameter> </method> +<field name="ERROR_ALREADY_MOUNTED" + type="int" + transient="false" + volatile="false" + value="24" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ERROR_COULD_NOT_MOUNT" + type="int" + transient="false" + volatile="false" + value="21" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ERROR_COULD_NOT_UNMOUNT" + type="int" + transient="false" + volatile="false" + value="22" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ERROR_INTERNAL" + type="int" + transient="false" + volatile="false" + value="20" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ERROR_NOT_MOUNTED" + type="int" + transient="false" + volatile="false" + value="23" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ERROR_PERMISSION_DENIED" + type="int" + transient="false" + volatile="false" + value="25" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="MOUNTED" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="UNMOUNTED" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> </class> <class name="StorageEventListener" extends="java.lang.Object" @@ -143708,8 +143796,6 @@ > <parameter name="filename" type="java.lang.String"> </parameter> -<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> -</exception> </method> <method name="isUsbMassStorageConnected" return="boolean" @@ -198458,6 +198544,17 @@ visibility="public" > </field> +<field name="SHOW_AS_ACTION_WITH_TEXT" + type="int" + transient="false" + volatile="false" + value="4" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> </interface> <interface name="MenuItem.OnMenuItemClickListener" abstract="true" @@ -225433,6 +225530,23 @@ </parameter> <parameter name="offset" type="int"> </parameter> +<parameter name="duration" type="int"> +</parameter> +</method> +<method name="smoothScrollToPositionFromTop" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="position" type="int"> +</parameter> +<parameter name="offset" type="int"> +</parameter> </method> <method name="verifyDrawable" return="boolean" diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 4d0b8b0..a486ccc 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -5282,7 +5282,14 @@ public class Intent implements Parcelable, Cloneable { b.append(' '); } first = false; - b.append("dat=").append(mData); + b.append("dat="); + if (mData.getScheme().equalsIgnoreCase("tel")) { + b.append("tel:xxx-xxx-xxxx"); + } else if (mData.getScheme().equalsIgnoreCase("smsto")) { + b.append("smsto:xxx-xxx-xxxx"); + } else { + b.append(mData); + } } if (mType != null) { if (!first) { diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index 0639573..bae6ad3 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -411,7 +411,7 @@ public class SyncStorageEngine extends Handler { } public void setSyncAutomatically(Account account, String providerName, boolean sync) { - Log.d(TAG, "setSyncAutomatically: " + account + ", provider " + providerName + Log.d(TAG, "setSyncAutomatically: " + /*account +*/ ", provider " + providerName + " -> " + sync); synchronized (mAuthorities) { AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false); diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index c185007..de5b7b9 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -38,7 +38,10 @@ import java.util.HashMap; * network access on the application's main thread, where UI * operations are received and animations take place. Keeping disk * and network operations off the main thread makes for much smoother, - * more responsive applications. + * more responsive applications. By keeping your application's main thread + * responsive, you also prevent + * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> + * from being shown to users. * * <p class="note">Note that even though an Android device's disk is * often on flash memory, many devices run a filesystem on top of that diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 57e208a..3a2add4 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -484,7 +484,7 @@ public interface IMountService extends IInterface { * IObbActionListener to inform it of the terminal state of the * call. */ - public void mountObb(String filename, String key, IObbActionListener token) + public void mountObb(String filename, String key, IObbActionListener token, int nonce) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); @@ -493,6 +493,7 @@ public interface IMountService extends IInterface { _data.writeString(filename); _data.writeString(key); _data.writeStrongBinder((token != null ? token.asBinder() : null)); + _data.writeInt(nonce); mRemote.transact(Stub.TRANSACTION_mountObb, _data, _reply, 0); _reply.readException(); } finally { @@ -508,8 +509,8 @@ public interface IMountService extends IInterface { * IObbActionListener to inform it of the terminal state of the * call. */ - public void unmountObb(String filename, boolean force, IObbActionListener token) - throws RemoteException { + public void unmountObb(String filename, boolean force, IObbActionListener token, + int nonce) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { @@ -517,6 +518,7 @@ public interface IMountService extends IInterface { _data.writeString(filename); _data.writeInt((force ? 1 : 0)); _data.writeStrongBinder((token != null ? token.asBinder() : null)); + _data.writeInt(nonce); mRemote.transact(Stub.TRANSACTION_unmountObb, _data, _reply, 0); _reply.readException(); } finally { @@ -876,7 +878,9 @@ public interface IMountService extends IInterface { key = data.readString(); IObbActionListener observer; observer = IObbActionListener.Stub.asInterface(data.readStrongBinder()); - mountObb(filename, key, observer); + int nonce; + nonce = data.readInt(); + mountObb(filename, key, observer, nonce); reply.writeNoException(); return true; } @@ -888,7 +892,9 @@ public interface IMountService extends IInterface { force = 0 != data.readInt(); IObbActionListener observer; observer = IObbActionListener.Stub.asInterface(data.readStrongBinder()); - unmountObb(filename, force, observer); + int nonce; + nonce = data.readInt(); + unmountObb(filename, force, observer, nonce); reply.writeNoException(); return true; } @@ -1007,7 +1013,7 @@ public interface IMountService extends IInterface { * MountService will call back to the supplied IObbActionListener to inform * it of the terminal state of the call. */ - public void mountObb(String filename, String key, IObbActionListener token) + public void mountObb(String filename, String key, IObbActionListener token, int nonce) throws RemoteException; /* @@ -1051,7 +1057,7 @@ public interface IMountService extends IInterface { * MountService will call back to the supplied IObbActionListener to inform * it of the terminal state of the call. */ - public void unmountObb(String filename, boolean force, IObbActionListener token) + public void unmountObb(String filename, boolean force, IObbActionListener token, int nonce) throws RemoteException; /* diff --git a/core/java/android/os/storage/IObbActionListener.java b/core/java/android/os/storage/IObbActionListener.java index 2c098ac..d6fa58a 100644 --- a/core/java/android/os/storage/IObbActionListener.java +++ b/core/java/android/os/storage/IObbActionListener.java @@ -69,9 +69,11 @@ public interface IObbActionListener extends IInterface { data.enforceInterface(DESCRIPTOR); String filename; filename = data.readString(); - String status; - status = data.readString(); - this.onObbResult(filename, status); + int nonce; + nonce = data.readInt(); + int status; + status = data.readInt(); + this.onObbResult(filename, nonce, status); reply.writeNoException(); return true; } @@ -101,13 +103,15 @@ public interface IObbActionListener extends IInterface { * on * @param returnCode status of the operation */ - public void onObbResult(String filename, String status) throws RemoteException { + public void onObbResult(String filename, int nonce, int status) + throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(filename); - _data.writeString(status); + _data.writeInt(nonce); + _data.writeInt(status); mRemote.transact(Stub.TRANSACTION_onObbResult, _data, _reply, 0); _reply.readException(); } finally { @@ -124,7 +128,8 @@ public interface IObbActionListener extends IInterface { * Return from an OBB action result. * * @param filename the path to the OBB the operation was performed on - * @param returnCode status of the operation + * @param nonce identifier that is meaningful to the receiver + * @param status status code as defined in {@link OnObbStateChangeListener} */ - public void onObbResult(String filename, String status) throws RemoteException; + public void onObbResult(String filename, int nonce, int status) throws RemoteException; } diff --git a/core/java/android/os/storage/OnObbStateChangeListener.java b/core/java/android/os/storage/OnObbStateChangeListener.java index a2d0a56..950195b 100644 --- a/core/java/android/os/storage/OnObbStateChangeListener.java +++ b/core/java/android/os/storage/OnObbStateChangeListener.java @@ -17,15 +17,69 @@ package android.os.storage; /** - * Used for receiving notifications from {@link StorageManager}. + * Used for receiving notifications from {@link StorageManager} about OBB file + * states. */ public abstract class OnObbStateChangeListener { + + /** + * The OBB container is now mounted and ready for use. Returned in status + * messages from calls made via {@link StorageManager} + */ + public static final int MOUNTED = 1; + + /** + * The OBB container is now unmounted and not usable. Returned in status + * messages from calls made via {@link StorageManager} + */ + public static final int UNMOUNTED = 2; + + /** + * There was an internal system error encountered while trying to mount the + * OBB. Returned in status messages from calls made via + * {@link StorageManager} + */ + public static final int ERROR_INTERNAL = 20; + + /** + * The OBB could not be mounted by the system. Returned in status messages + * from calls made via {@link StorageManager} + */ + public static final int ERROR_COULD_NOT_MOUNT = 21; + + /** + * The OBB could not be unmounted. This most likely indicates that a file is + * in use on the OBB. Returned in status messages from calls made via + * {@link StorageManager} + */ + public static final int ERROR_COULD_NOT_UNMOUNT = 22; + + /** + * A call was made to unmount the OBB when it was not mounted. Returned in + * status messages from calls made via {@link StorageManager} + */ + public static final int ERROR_NOT_MOUNTED = 23; + + /** + * The OBB has already been mounted. Returned in status messages from calls + * made via {@link StorageManager} + */ + public static final int ERROR_ALREADY_MOUNTED = 24; + + /** + * The current application does not have permission to use this OBB because + * the OBB indicates it's owned by a different package or the key used to + * open it is incorrect. Returned in status messages from calls made via + * {@link StorageManager} + */ + public static final int ERROR_PERMISSION_DENIED = 25; + /** * Called when an OBB has changed states. * * @param path path to the OBB file the state change has happened on * @param state the current state of the OBB */ - public void onObbStateChange(String path, String state) { + public void onObbStateChange(String path, int state) { } } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 8554ece..fb76937 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -22,12 +22,13 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import android.util.Slog; +import android.util.SparseArray; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; /** * StorageManager is the interface to the systems storage service. The storage @@ -69,7 +70,12 @@ public class StorageManager /* * List of our listeners */ - private ArrayList<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>(); + private List<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>(); + + /* + * Next available nonce + */ + final private AtomicInteger mNextNonce = new AtomicInteger(0); private class MountServiceBinderListener extends IMountServiceListener.Stub { public void onUsbMassStorageConnectionChanged(boolean available) { @@ -93,57 +99,38 @@ public class StorageManager private final ObbActionListener mObbActionListener = new ObbActionListener(); private class ObbActionListener extends IObbActionListener.Stub { - private List<WeakReference<ObbListenerDelegate>> mListeners = new LinkedList<WeakReference<ObbListenerDelegate>>(); + private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>(); @Override - public void onObbResult(String filename, String status) throws RemoteException { + public void onObbResult(String filename, int nonce, int status) throws RemoteException { + final ObbListenerDelegate delegate; synchronized (mListeners) { - final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator(); - while (iter.hasNext()) { - final WeakReference<ObbListenerDelegate> ref = iter.next(); - - final ObbListenerDelegate delegate = (ref == null) ? null : ref.get(); - if (delegate == null) { - iter.remove(); - continue; - } - - delegate.sendObbStateChanged(filename, status); + delegate = mListeners.get(nonce); + if (delegate != null) { + mListeners.remove(nonce); } } - } - public void addListener(OnObbStateChangeListener listener) { - if (listener == null) { - return; + if (delegate != null) { + delegate.sendObbStateChanged(filename, status); } + } - synchronized (mListeners) { - final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator(); - while (iter.hasNext()) { - final WeakReference<ObbListenerDelegate> ref = iter.next(); - - final ObbListenerDelegate delegate = (ref == null) ? null : ref.get(); - if (delegate == null) { - iter.remove(); - continue; - } - - /* - * If we're already in the listeners, we don't need to be in - * there again. - */ - if (listener.equals(delegate.getListener())) { - return; - } - } + public int addListener(OnObbStateChangeListener listener) { + final ObbListenerDelegate delegate = new ObbListenerDelegate(listener); - final ObbListenerDelegate delegate = new ObbListenerDelegate(listener); - mListeners.add(new WeakReference<ObbListenerDelegate>(delegate)); + synchronized (mListeners) { + mListeners.put(delegate.nonce, delegate); } + + return delegate.nonce; } } + private int getNextNonce() { + return mNextNonce.getAndIncrement(); + } + /** * Private class containing sender and receiver code for StorageEvents. */ @@ -151,7 +138,10 @@ public class StorageManager private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef; private final Handler mHandler; + private final int nonce; + ObbListenerDelegate(OnObbStateChangeListener listener) { + nonce = getNextNonce(); mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener); mHandler = new Handler(mTgtLooper) { @Override @@ -180,7 +170,7 @@ public class StorageManager return mObbEventListenerRef.get(); } - void sendObbStateChanged(String path, String state) { + void sendObbStateChanged(String path, int state) { ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state); mHandler.sendMessage(e.getMessage()); } @@ -191,9 +181,10 @@ public class StorageManager */ private class ObbStateChangedStorageEvent extends StorageEvent { public final String path; - public final String state; - public ObbStateChangedStorageEvent(String path, String state) { + public final int state; + + public ObbStateChangedStorageEvent(String path, int state) { super(EVENT_OBB_STATE_CHANGED); this.path = path; this.state = state; @@ -410,10 +401,8 @@ public class StorageManager * <p> * The OBB will remain mounted for as long as the StorageManager reference * is held by the application. As soon as this reference is lost, the OBBs - * in use will be unmounted. The {@link OnObbStateChangeListener} registered with - * this call will receive all further OBB-related events until it goes out - * of scope. If the caller is not interested in whether the call succeeds, - * the <code>listener</code> may be specified as <code>null</code>. + * in use will be unmounted. The {@link OnObbStateChangeListener} registered + * with this call will receive the success or failure of this operation. * <p> * <em>Note:</em> you can only mount OBB files for which the OBB tag on the * file matches a package ID that is owned by the calling program's UID. @@ -423,12 +412,21 @@ public class StorageManager * @param filename the path to the OBB file * @param key secret used to encrypt the OBB; may be <code>null</code> if no * encryption was used on the OBB. + * @param listener will receive the success or failure of the operation * @return whether the mount call was successfully queued or not */ public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) { + if (filename == null) { + throw new IllegalArgumentException("filename cannot be null"); + } + + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + try { - mObbActionListener.addListener(listener); - mMountService.mountObb(filename, key, mObbActionListener); + final int nonce = mObbActionListener.addListener(listener); + mMountService.mountObb(filename, key, mObbActionListener, nonce); return true; } catch (RemoteException e) { Log.e(TAG, "Failed to mount OBB", e); @@ -442,10 +440,8 @@ public class StorageManager * <code>force</code> flag is true, it will kill any application needed to * unmount the given OBB (even the calling application). * <p> - * The {@link OnObbStateChangeListener} registered with this call will receive all - * further OBB-related events until it goes out of scope. If the caller is - * not interested in whether the call succeeded, the listener may be - * specified as <code>null</code>. + * The {@link OnObbStateChangeListener} registered with this call will + * receive the success or failure of this operation. * <p> * <em>Note:</em> you can only mount OBB files for which the OBB tag on the * file matches a package ID that is owned by the calling program's UID. @@ -456,12 +452,21 @@ public class StorageManager * @param filename path to the OBB file * @param force whether to kill any programs using this in order to unmount * it + * @param listener will receive the success or failure of the operation * @return whether the unmount call was successfully queued or not */ public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener) { + if (filename == null) { + throw new IllegalArgumentException("filename cannot be null"); + } + + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + try { - mObbActionListener.addListener(listener); - mMountService.unmountObb(filename, force, mObbActionListener); + final int nonce = mObbActionListener.addListener(listener); + mMountService.unmountObb(filename, force, mObbActionListener, nonce); return true; } catch (RemoteException e) { Log.e(TAG, "Failed to mount OBB", e); @@ -476,7 +481,11 @@ public class StorageManager * @param filename path to OBB image * @return true if OBB is mounted; false if not mounted or on error */ - public boolean isObbMounted(String filename) throws IllegalArgumentException { + public boolean isObbMounted(String filename) { + if (filename == null) { + throw new IllegalArgumentException("filename cannot be null"); + } + try { return mMountService.isObbMounted(filename); } catch (RemoteException e) { @@ -496,12 +505,14 @@ public class StorageManager * not mounted or exception encountered trying to read status */ public String getMountedObbPath(String filename) { + if (filename == null) { + throw new IllegalArgumentException("filename cannot be null"); + } + try { return mMountService.getMountedObbPath(filename); } catch (RemoteException e) { Log.e(TAG, "Failed to find mounted path for OBB", e); - } catch (IllegalArgumentException e) { - Log.d(TAG, "Couldn't read OBB file", e); } return null; diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index fa5cd8b..803446f 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -1215,9 +1215,8 @@ public final class Telephony { } Uri uri = uriBuilder.build(); - if (DEBUG) { - Log.v(TAG, "getOrCreateThreadId uri: " + uri); - } + //if (DEBUG) Log.v(TAG, "getOrCreateThreadId uri: " + uri); + Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(), uri, ID_PROJECTION, null, null, null); if (DEBUG) { diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java index 8b9d659..99da43b 100644 --- a/core/java/android/view/MenuItem.java +++ b/core/java/android/view/MenuItem.java @@ -45,6 +45,12 @@ public interface MenuItem { * A good rule of thumb is to have no more than 2 items set to always show at a time. */ public static final int SHOW_AS_ACTION_ALWAYS = 2; + + /** + * When this item is in the action bar, always show it with a text label even if + * it also has an icon specified. + */ + public static final int SHOW_AS_ACTION_WITH_TEXT = 4; /** * Interface definition for a callback to be invoked when a menu item is diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index f413475..85981d2 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -37,7 +37,11 @@ public class ViewConfiguration { * @hide */ public static final float ALPHA_THRESHOLD = 0.5f / PANEL_BIT_DEPTH; - + /** + * @hide + */ + public static final float ALPHA_THRESHOLD_INT = 0x7f / PANEL_BIT_DEPTH; + /** * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in * pixels diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index b1db5ca..4eea2d2 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2188,7 +2188,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager float alpha = child.getAlpha(); // Bail out early if the view does not need to be drawn - if (alpha <= ViewConfiguration.ALPHA_THRESHOLD && (child.mPrivateFlags & ALPHA_SET) == 0) { + if (alpha <= ViewConfiguration.ALPHA_THRESHOLD && (child.mPrivateFlags & ALPHA_SET) == 0 && + !(child instanceof SurfaceView)) { return more; } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index eddd04e..7cb4671 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -611,6 +611,19 @@ public interface WindowManager extends ViewManager { * {@hide} */ public static final int FLAG_SPLIT_TOUCH = 0x00800000; + /** + * Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU} + * and therefore needs a Menu key. For devices where Menu is a physical button this flag is + * ignored, but on devices where the Menu key is drawn in software it may be hidden unless + * this flag is set. + * + * (Note that Action Bars, when available, are the preferred way to offer additional + * functions otherwise accessed via an options menu.) + * + * {@hide} + */ + public static final int FLAG_NEEDS_MENU_KEY = 0x01000000; + /** Window flag: *sigh* The lock screen wants to continue running its * animation while it is fading. A kind-of hack to allow this. Maybe * in the future we just make this the default behavior. diff --git a/core/java/android/webkit/DebugFlags.java b/core/java/android/webkit/DebugFlags.java index dca52f6..8e25395 100644 --- a/core/java/android/webkit/DebugFlags.java +++ b/core/java/android/webkit/DebugFlags.java @@ -32,8 +32,6 @@ class DebugFlags { public static final boolean CALLBACK_PROXY = false; public static final boolean COOKIE_MANAGER = false; public static final boolean COOKIE_SYNC_MANAGER = false; - public static final boolean DRAG_TRACKER = false; - public static final String DRAG_TRACKER_LOGTAG = "skia"; public static final boolean FRAME_LOADER = false; public static final boolean J_WEB_CORE_JAVA_BRIDGE = false;// HIGHLY VERBOSE public static final boolean LOAD_LISTENER = false; diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index c42c601..4689740 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -226,20 +226,41 @@ public class WebSettings { public static class AutoFillProfile { private String mFullName; private String mEmailAddress; - - public AutoFillProfile() { - } - - public AutoFillProfile(String fullName, String email) { + private String mCompanyName; + private String mAddressLine1; + private String mAddressLine2; + private String mCity; + private String mState; + private String mZipCode; + private String mCountry; + private String mPhoneNumber; + + public AutoFillProfile(String fullName, String email, + String companyName, String addressLine1, String addressLine2, + String city, String state, String zipCode, String country, + String phoneNumber) { mFullName = fullName; mEmailAddress = email; + mCompanyName = companyName; + mAddressLine1 = addressLine1; + mAddressLine2 = addressLine2; + mCity = city; + mState = state; + mZipCode = zipCode; + mCountry = country; + mPhoneNumber = phoneNumber; } - public void setFullName(String fullName) { mFullName = fullName; } - public void setEmailAddress(String emailAddress) { mEmailAddress = emailAddress; } - public String getFullName() { return mFullName; } public String getEmailAddress() { return mEmailAddress; } + public String getCompanyName() { return mCompanyName; } + public String getAddressLine1() { return mAddressLine1; } + public String getAddressLine2() { return mAddressLine2; } + public String getCity() { return mCity; } + public String getState() { return mState; } + public String getZipCode() { return mZipCode; } + public String getCountry() { return mCountry; } + public String getPhoneNumber() { return mPhoneNumber; } } diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 1aff170..812e126 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -583,6 +583,7 @@ import java.util.ArrayList; return false; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + super.onTouchEvent(event); if (mHasPerformedLongClick) { mGotTouchDown = false; return false; @@ -780,9 +781,6 @@ import java.util.ArrayList; // webkit's drawing. setWillNotDraw(!inPassword); setBackgroundDrawable(inPassword ? mBackground : null); - // For non-password fields, avoid the invals from TextView's blinking - // cursor - setCursorVisible(inPassword); } /** diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index ea29d5e..a7e51a4 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -33,7 +33,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.CornerPathEffect; import android.graphics.DrawFilter; -import android.graphics.Interpolator; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.graphics.Picture; @@ -48,7 +47,6 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.os.SystemClock; import android.provider.Settings; import android.speech.tts.TextToSpeech; import android.text.Selection; @@ -93,8 +91,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; @@ -309,8 +305,6 @@ public class WebView extends AbsoluteLayout implements ViewTreeObserver.OnGlobalFocusChangeListener, ViewGroup.OnHierarchyChangeListener { - // enable debug output for drag trackers - private static final boolean DEBUG_DRAG_TRACKER = false; // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing // the screen all-the-time. Good for profiling our drawing code static private final boolean AUTO_REDRAW_HACK = false; @@ -3464,17 +3458,7 @@ public class WebView extends AbsoluteLayout if (mTitleBar != null) { canvas.translate(0, (int) mTitleBar.getHeight()); } - if (mDragTrackerHandler == null) { - drawContent(canvas); - } else { - if (!mDragTrackerHandler.draw(canvas)) { - // sometimes the tracker doesn't draw, even though its active - drawContent(canvas); - } - if (mDragTrackerHandler.isFinished()) { - mDragTrackerHandler = null; - } - } + drawContent(canvas); canvas.restoreToCount(saveCount); // Now draw the shadow. @@ -4724,207 +4708,6 @@ public class WebView extends AbsoluteLayout private static final float MAX_SLOPE_FOR_DIAG = 1.5f; private static final int MIN_BREAK_SNAP_CROSS_DISTANCE = 80; - private static int sign(float x) { - return x > 0 ? 1 : (x < 0 ? -1 : 0); - } - - // if the page can scroll <= this value, we won't allow the drag tracker - // to have any effect. - private static final int MIN_SCROLL_AMOUNT_TO_DISABLE_DRAG_TRACKER = 4; - - private class DragTrackerHandler { - private final DragTracker mProxy; - private final float mStartY, mStartX; - private final float mMinDY, mMinDX; - private final float mMaxDY, mMaxDX; - private float mCurrStretchY, mCurrStretchX; - private int mSX, mSY; - private Interpolator mInterp; - private float[] mXY = new float[2]; - - // inner (non-state) classes can't have enums :( - private static final int DRAGGING_STATE = 0; - private static final int ANIMATING_STATE = 1; - private static final int FINISHED_STATE = 2; - private int mState; - - public DragTrackerHandler(float x, float y, DragTracker proxy) { - mProxy = proxy; - - int docBottom = computeVerticalScrollRange() + getTitleHeight(); - int viewTop = getScrollY(); - int viewBottom = viewTop + getHeight(); - - mStartY = y; - mMinDY = -viewTop; - mMaxDY = docBottom - viewBottom; - - if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { - Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " dragtracker y= " + y + - " up/down= " + mMinDY + " " + mMaxDY); - } - - int docRight = computeHorizontalScrollRange(); - int viewLeft = getScrollX(); - int viewRight = viewLeft + getWidth(); - mStartX = x; - mMinDX = -viewLeft; - mMaxDX = docRight - viewRight; - - mState = DRAGGING_STATE; - mProxy.onStartDrag(x, y); - - // ensure we buildBitmap at least once - mSX = -99999; - } - - private float computeStretch(float delta, float min, float max) { - float stretch = 0; - if (max - min > MIN_SCROLL_AMOUNT_TO_DISABLE_DRAG_TRACKER) { - if (delta < min) { - stretch = delta - min; - } else if (delta > max) { - stretch = delta - max; - } - } - return stretch; - } - - public void dragTo(float x, float y) { - float sy = computeStretch(mStartY - y, mMinDY, mMaxDY); - float sx = computeStretch(mStartX - x, mMinDX, mMaxDX); - - if ((mSnapScrollMode & SNAP_X) != 0) { - sy = 0; - } else if ((mSnapScrollMode & SNAP_Y) != 0) { - sx = 0; - } - - if (mCurrStretchX != sx || mCurrStretchY != sy) { - mCurrStretchX = sx; - mCurrStretchY = sy; - if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { - Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "---- stretch " + sx + - " " + sy); - } - if (mProxy.onStretchChange(sx, sy)) { - invalidate(); - } - } - } - - public void stopDrag() { - final int DURATION = 200; - int now = (int)SystemClock.uptimeMillis(); - mInterp = new Interpolator(2); - mXY[0] = mCurrStretchX; - mXY[1] = mCurrStretchY; - // float[] blend = new float[] { 0.5f, 0, 0.75f, 1 }; - float[] blend = new float[] { 0, 0.5f, 0.75f, 1 }; - mInterp.setKeyFrame(0, now, mXY, blend); - float[] zerozero = new float[] { 0, 0 }; - mInterp.setKeyFrame(1, now + DURATION, zerozero, null); - mState = ANIMATING_STATE; - - if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { - Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "----- stopDrag, starting animation"); - } - } - - // Call this after each draw. If it ruturns null, the tracker is done - public boolean isFinished() { - return mState == FINISHED_STATE; - } - - private int hiddenHeightOfTitleBar() { - return getTitleHeight() - getVisibleTitleHeight(); - } - - // need a way to know if 565 or 8888 is the right config for - // capturing the display and giving it to the drag proxy - private Bitmap.Config offscreenBitmapConfig() { - // hard code 565 for now - return Bitmap.Config.RGB_565; - } - - /* If the tracker draws, then this returns true, otherwise it will - return false, and draw nothing. - */ - public boolean draw(Canvas canvas) { - if (mCurrStretchX != 0 || mCurrStretchY != 0) { - int sx = getScrollX(); - int sy = getScrollY() - hiddenHeightOfTitleBar(); - if (mSX != sx || mSY != sy) { - buildBitmap(sx, sy); - mSX = sx; - mSY = sy; - } - - if (mState == ANIMATING_STATE) { - Interpolator.Result result = mInterp.timeToValues(mXY); - if (result == Interpolator.Result.FREEZE_END) { - mState = FINISHED_STATE; - return false; - } else { - mProxy.onStretchChange(mXY[0], mXY[1]); - invalidate(); - // fall through to the draw - } - } - int count = canvas.save(Canvas.MATRIX_SAVE_FLAG); - canvas.translate(sx, sy); - mProxy.onDraw(canvas); - canvas.restoreToCount(count); - return true; - } - if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { - Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " -- draw false " + - mCurrStretchX + " " + mCurrStretchY); - } - return false; - } - - private void buildBitmap(int sx, int sy) { - int w = getWidth(); - int h = getViewHeight(); - Bitmap bm = Bitmap.createBitmap(w, h, offscreenBitmapConfig()); - Canvas canvas = new Canvas(bm); - canvas.translate(-sx, -sy); - drawContent(canvas); - - if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { - Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "--- buildBitmap " + sx + - " " + sy + " " + w + " " + h); - } - mProxy.onBitmapChange(bm); - } - } - - /** @hide */ - public static class DragTracker { - public void onStartDrag(float x, float y) {} - public boolean onStretchChange(float sx, float sy) { - // return true to have us inval the view - return false; - } - public void onStopDrag() {} - public void onBitmapChange(Bitmap bm) {} - public void onDraw(Canvas canvas) {} - } - - /** @hide */ - public DragTracker getDragTracker() { - return mDragTracker; - } - - /** @hide */ - public void setDragTracker(DragTracker tracker) { - mDragTracker = tracker; - } - - private DragTracker mDragTracker; - private DragTrackerHandler mDragTrackerHandler; - private boolean hitFocusedPlugin(int contentX, int contentY) { if (DebugFlags.WEB_VIEW) { Log.v(LOGTAG, "nativeFocusIsPlugin()=" + nativeFocusIsPlugin()); @@ -5330,10 +5113,6 @@ public class WebView extends AbsoluteLayout startDrag(); } - if (mDragTrackerHandler != null) { - mDragTrackerHandler.dragTo(x, y); - } - // do pan if (mTouchMode != TOUCH_DRAG_LAYER_MODE) { int newScrollX = pinLocX(mScrollX + deltaX); @@ -5607,9 +5386,6 @@ public class WebView extends AbsoluteLayout mLastTouchTime = eventTime; mVelocityTracker = VelocityTracker.obtain(); mSnapScrollMode = SNAP_NONE; - if (mDragTracker != null) { - mDragTrackerHandler = new DragTrackerHandler(x, y, mDragTracker); - } } private void startDrag() { @@ -5642,9 +5418,6 @@ public class WebView extends AbsoluteLayout } private void stopTouch() { - if (mDragTrackerHandler != null) { - mDragTrackerHandler.stopDrag(); - } // we also use mVelocityTracker == null to tell us that we are // not "moving around", so we can take the slower/prettier // mode in the drawing code @@ -5655,9 +5428,6 @@ public class WebView extends AbsoluteLayout } private void cancelTouch() { - if (mDragTrackerHandler != null) { - mDragTrackerHandler.stopDrag(); - } // we also use mVelocityTracker == null to tell us that we are // not "moving around", so we can take the slower/prettier // mode in the drawing code diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 4d77a7a..f295c41 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -3050,6 +3050,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } void startWithOffset(int position, int offset) { + startWithOffset(position, offset, SCROLL_DURATION); + } + + void startWithOffset(int position, int offset, int duration) { mTargetPos = position; mOffsetFromTop = offset; mBoundPos = INVALID_POSITION; @@ -3068,14 +3072,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } else { // On-screen, just scroll. final int targetTop = getChildAt(position - firstPos).getTop(); - smoothScrollBy(targetTop - offset, SCROLL_DURATION); + smoothScrollBy(targetTop - offset, duration); return; } // Estimate how many screens we should travel final float screenTravelCount = (float) viewTravelCount / childCount; - mScrollDuration = screenTravelCount < 1 ? (int) (screenTravelCount * SCROLL_DURATION) : - (int) (SCROLL_DURATION / screenTravelCount); + mScrollDuration = screenTravelCount < 1 ? (int) (screenTravelCount * duration) : + (int) (duration / screenTravelCount); mLastSeenPos = INVALID_POSITION; post(this); @@ -3284,7 +3288,26 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } mPositionScroller.start(position); } - + + /** + * Smoothly scroll to the specified adapter position. The view will scroll + * such that the indicated position is displayed <code>offset</code> pixels from + * the top edge of the view. If this is impossible, (e.g. the offset would scroll + * the first or last item beyond the boundaries of the list) it will get as close + * as possible. The scroll will take <code>duration</code> milliseconds to complete. + * + * @param position Position to scroll to + * @param offset Desired distance in pixels of <code>position</code> from the top + * of the view when scrolling is finished + * @param duration Number of milliseconds to use for the scroll + */ + public void smoothScrollToPositionFromTop(int position, int offset, int duration) { + if (mPositionScroller == null) { + mPositionScroller = new PositionScroller(); + } + mPositionScroller.startWithOffset(position, offset, duration); + } + /** * Smoothly scroll to the specified adapter position. The view will scroll * such that the indicated position is displayed <code>offset</code> pixels from diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 57fd251..09a19cd 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -16,6 +16,7 @@ package android.widget; +import android.view.ViewConfiguration; import com.android.internal.util.FastMath; import com.android.internal.widget.EditableInputConnection; @@ -97,6 +98,7 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; +import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; import android.view.ViewRoot; @@ -3954,6 +3956,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override protected void onDraw(Canvas canvas) { + if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return; + restartMarqueeIfNeeded(); // Draw the background for this view @@ -6943,8 +6947,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private void prepareCursorControllers() { + boolean windowSupportsHandles = false; + + ViewGroup.LayoutParams params = getRootView().getLayoutParams(); + if (params instanceof WindowManager.LayoutParams) { + WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params; + windowSupportsHandles = windowParams.type < WindowManager.LayoutParams.FIRST_SUB_WINDOW + || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW; + } + // TODO Add an extra android:cursorController flag to disable the controller? - if (mCursorVisible && mLayout != null) { + if (windowSupportsHandles && mCursorVisible && mLayout != null) { if (mInsertionPointCursorController == null) { mInsertionPointCursorController = new InsertionPointCursorController(); } @@ -6952,7 +6965,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mInsertionPointCursorController = null; } - if (textCanBeSelected() && mLayout != null) { + if (windowSupportsHandles && textCanBeSelected() && mLayout != null) { if (mSelectionModifierCursorController == null) { mSelectionModifierCursorController = new SelectionModifierCursorController(); } @@ -7047,6 +7060,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override protected float getLeftFadingEdgeStrength() { + if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return 0.0f; if (mEllipsize == TextUtils.TruncateAt.MARQUEE) { if (mMarquee != null && !mMarquee.isStopped()) { final Marquee marquee = mMarquee; @@ -7073,6 +7087,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override protected float getRightFadingEdgeStrength() { + if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return 0.0f; if (mEllipsize == TextUtils.TruncateAt.MARQUEE) { if (mMarquee != null && !mMarquee.isStopped()) { final Marquee marquee = mMarquee; @@ -7708,28 +7723,36 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (canSelectText()) { menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll). setIcon(com.android.internal.R.drawable.ic_menu_select_all). - setAlphabeticShortcut('a'); + setAlphabeticShortcut('a'). + setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); atLeastOne = true; } if (canCut()) { menu.add(0, ID_CUT, 0, com.android.internal.R.string.cut). setIcon(styledAttributes.getResourceId(R.styleable.Theme_actionModeCutDrawable, 0)). - setAlphabeticShortcut('x'); + setAlphabeticShortcut('x'). + setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); atLeastOne = true; } if (canCopy()) { menu.add(0, ID_COPY, 0, com.android.internal.R.string.copy). setIcon(styledAttributes.getResourceId(R.styleable.Theme_actionModeCopyDrawable, 0)). - setAlphabeticShortcut('c'); + setAlphabeticShortcut('c'). + setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); atLeastOne = true; } if (canPaste()) { menu.add(0, ID_PASTE, 0, com.android.internal.R.string.paste). setIcon(styledAttributes.getResourceId(R.styleable.Theme_actionModePasteDrawable, 0)). - setAlphabeticShortcut('v'); + setAlphabeticShortcut('v'). + setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); atLeastOne = true; } diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index e884af8..34a5b11 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -31,5 +31,6 @@ oneway interface IStatusBar void animateExpand(); void animateCollapse(); void setLightsOn(boolean on); + void setMenuKeyVisible(boolean visible); } diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 0763f5e..90f4d48 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -31,12 +31,13 @@ interface IStatusBarService void setIconVisibility(String slot, boolean visible); void removeIcon(String slot); void setActiveWindowIsFullscreen(boolean fullscreen); + void setMenuKeyVisible(boolean visible); // ---- Methods below are for use by the status bar policy services ---- // You need the STATUS_BAR_SERVICE permission void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList, out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications, - out boolean[] lightsOn); + out boolean[] switches); void onPanelRevealed(); void onNotificationClick(String pkg, String tag, int id); void onNotificationError(String pkg, String tag, int id, diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java index f97bfb4..d5f69ba 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java @@ -21,13 +21,13 @@ import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import android.widget.Button; -import android.widget.FrameLayout; import android.widget.ImageButton; +import android.widget.LinearLayout; /** * @hide */ -public class ActionMenuItemView extends FrameLayout +public class ActionMenuItemView extends LinearLayout implements MenuView.ItemView, View.OnClickListener { private static final String TAG = "ActionMenuItemView"; @@ -65,8 +65,6 @@ public class ActionMenuItemView extends FrameLayout public void initialize(MenuItemImpl itemData, int menuType) { mItemData = itemData; - setClickable(true); - setFocusable(true); setIcon(itemData.getIcon()); setTitle(itemData.getTitle()); // Title only takes effect if there is no icon setId(itemData.getItemId()); @@ -128,7 +126,7 @@ public class ActionMenuItemView extends FrameLayout // populate accessibility description with title setContentDescription(title); - if (mImageButton.getDrawable() == null) { + if (mImageButton.getDrawable() == null || mItemData.showsTextAsAction()) { mTextButton.setText(mTitle); mTextButton.setVisibility(VISIBLE); } diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 42f9771..8eee360 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -38,6 +38,10 @@ import com.android.internal.view.menu.MenuView.ItemView; public final class MenuItemImpl implements MenuItem { private static final String TAG = "MenuItemImpl"; + private static final int SHOW_AS_ACTION_MASK = SHOW_AS_ACTION_NEVER | + SHOW_AS_ACTION_IF_ROOM | + SHOW_AS_ACTION_ALWAYS; + private final int mId; private final int mGroup; private final int mCategoryOrder; @@ -649,11 +653,11 @@ public final class MenuItemImpl implements MenuItem { } public boolean requestsActionButton() { - return mShowAsAction == SHOW_AS_ACTION_IF_ROOM; + return (mShowAsAction & SHOW_AS_ACTION_IF_ROOM) == SHOW_AS_ACTION_IF_ROOM; } public boolean requiresActionButton() { - return mShowAsAction == SHOW_AS_ACTION_ALWAYS; + return (mShowAsAction & SHOW_AS_ACTION_ALWAYS) == SHOW_AS_ACTION_ALWAYS; } public void setIsActionButton(boolean isActionButton) { @@ -664,7 +668,23 @@ public final class MenuItemImpl implements MenuItem { } } + public boolean showsTextAsAction() { + return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT; + } + public void setShowAsAction(int actionEnum) { + switch (actionEnum & SHOW_AS_ACTION_MASK) { + case SHOW_AS_ACTION_ALWAYS: + case SHOW_AS_ACTION_IF_ROOM: + case SHOW_AS_ACTION_NEVER: + // Looks good! + break; + + default: + // Mutually exclusive options selected! + throw new IllegalArgumentException("SHOW_AS_ACTION_ALWAYS, SHOW_AS_ACTION_IF_ROOM," + + " and SHOW_AS_ACTION_NEVER are mutually exclusive."); + } mShowAsAction = actionEnum; mMenu.onItemActionRequestChanged(this); } diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index bf150a9..8944d47 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -26,9 +26,6 @@ #include "SkShader.h" #include "SkTemplates.h" -#include "SkBoundaryPatch.h" -#include "SkMeshUtils.h" - #include "TextLayout.h" #include "unicode/ubidi.h" @@ -968,40 +965,6 @@ static JNINativeMethod gCanvasMethods[] = { /////////////////////////////////////////////////////////////////////////////// -static void BoundaryPatch_computeCubic(JNIEnv* env, jobject, jfloatArray jpts, - int texW, int texH, int rows, int cols, - jfloatArray jverts, jshortArray jidx) { - AutoJavaFloatArray ptsArray(env, jpts, 24, kRO_JNIAccess); - - int vertCount = rows * cols; - AutoJavaFloatArray vertsArray(env, jverts, vertCount * 4, kRW_JNIAccess); - SkPoint* verts = (SkPoint*)vertsArray.ptr(); - SkPoint* texs = verts + vertCount; - - int idxCount = (rows - 1) * (cols - 1) * 6; - AutoJavaShortArray idxArray(env, jidx, idxCount, kRW_JNIAccess); - uint16_t* idx = (uint16_t*)idxArray.ptr(); // cast from int16_t* - - SkCubicBoundary cubic; - memcpy(cubic.fPts, ptsArray.ptr(), 12 * sizeof(SkPoint)); - - SkBoundaryPatch patch; - patch.setBoundary(&cubic); - // generate our verts - patch.evalPatch(verts, rows, cols); - - SkMeshIndices mesh; - // generate our texs and idx - mesh.init(texs, idx, texW, texH, rows, cols); -} - -static JNINativeMethod gBoundaryPatchMethods[] = { - {"nativeComputeCubicPatch", "([FIIII[F[S)V", - (void*)BoundaryPatch_computeCubic }, -}; - -/////////////////////////////////////////////////////////////////////////////// - #include <android_runtime/AndroidRuntime.h> #define REG(env, name, array) \ @@ -1013,7 +976,6 @@ int register_android_graphics_Canvas(JNIEnv* env) { int result; REG(env, "android/graphics/Canvas", gCanvasMethods); - REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods); return result; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 85e8a60..73341fe 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1341,10 +1341,6 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> - <activity android:name="com.android.internal.app.ExternalMediaFormatActivity" - android:theme="@style/Theme.Dialog.Alert" - android:excludeFromRecents="true"> - </activity> <activity android:name="android.accounts.ChooseAccountActivity" android:excludeFromRecents="true" diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index 830fb01..3e546a1 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -63,6 +63,9 @@ <item>@drawable/scrollbar_handle_horizontal</item> <item>@drawable/scrollbar_handle_vertical</item> <item>@drawable/spinner_dropdown_background</item> + <item>@drawable/text_select_handle_left</item> + <item>@drawable/text_select_handle_middle</item> + <item>@drawable/text_select_handle_right</item> <item>@drawable/title_bar</item> <item>@drawable/title_bar_shadow</item> <!-- Visual lock screen --> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 1ea6fc4..ef6d6cb 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3590,10 +3590,22 @@ <attr name="onClick" /> <!-- How this item should display in the Action Bar, if present. --> - <attr name="showAsAction" format="enum"> - <enum name="never" value="0" /> - <enum name="ifRoom" value="1" /> - <enum name="always" value="2" /> + <attr name="showAsAction"> + <!-- Never show this item in an action bar, show it in the overflow menu instead. + Mutually exclusive with "ifRoom" and "always". --> + <flag name="never" value="0" /> + <!-- Show this item in an action bar if there is room for it as determined + by the system. Favor this option over "always" where possible. + Mutually exclusive with "never" and "always". --> + <flag name="ifRoom" value="1" /> + <!-- Always show this item in an actionbar, even if it would override + the system's limits of how much stuff to put there. This may make + your action bar look bad on some screens. In most cases you should + use "ifRoom" instead. Mutually exclusive with "ifRoom" and "never". --> + <flag name="always" value="2" /> + <!-- When this item is shown as an action in the action bar, show a text + label with it even if it has an icon representation. --> + <flag name="withText" value="4" /> </attr> <!-- An optional layout to be used as an action view. diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index eed7e73..de2b930 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -174,9 +174,15 @@ Software implementation will be used if config_hardware_auto_brightness_available is not set --> <bool name="config_automatic_brightness_available">false</bool> + <!-- Don't name config resources like this. It should look like config_annoyDianne --> + <bool name="config_annoy_dianne">true</bool> + <!-- If this is true, the screen will come on when you unplug usb/power/whatever. --> <bool name="config_unplugTurnsOnScreen">false</bool> + <!-- If this is true, the screen will fade off. --> + <bool name="config_animateScreenLights">true</bool> + <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION --> <!-- The number of degrees to rotate the display when the keyboard is open. --> @@ -433,7 +439,7 @@ <string name="gsm_alphabet_default_charset"></string> <!-- Enables SIP on WIFI only --> - <bool name="config_sip_wifi_only">false</bool> + <bool name="config_sip_wifi_only">true</bool> <!-- Boolean indicating if restoring network selection should be skipped --> <!-- The restoring is handled by modem if it is true--> diff --git a/core/tests/coretests/src/com/android/server/MountServiceTests.java b/core/tests/coretests/src/com/android/server/MountServiceTests.java index 83e9d18..1f8c92e 100644 --- a/core/tests/coretests/src/com/android/server/MountServiceTests.java +++ b/core/tests/coretests/src/com/android/server/MountServiceTests.java @@ -21,7 +21,6 @@ import com.android.frameworks.coretests.R; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; -import android.os.Environment; import android.os.FileUtils; import android.os.storage.OnObbStateChangeListener; import android.os.storage.StorageManager; @@ -57,17 +56,15 @@ public class MountServiceTests extends AndroidTestCase { } } - private interface CompletableTask { - public boolean isDone(); - } + private static class ObbObserver extends OnObbStateChangeListener { + private String path; - private static class ObbObserver extends OnObbStateChangeListener implements CompletableTask { - public String path; - public String state; + public int state = -1; boolean done = false; @Override - public void onObbStateChange(String path, String state) { + public void onObbStateChange(String path, int state) { + Log.d(TAG, "Received message. path=" + path + ", state=" + state); synchronized (this) { this.path = path; this.state = state; @@ -76,32 +73,43 @@ public class MountServiceTests extends AndroidTestCase { } } + public String getPath() { + assertTrue("Expected ObbObserver to have received a state change.", done); + return path; + } + + public int getState() { + assertTrue("Expected ObbObserver to have received a state change.", done); + return state; + } + public void reset() { this.path = null; - this.state = null; + this.state = -1; done = false; } public boolean isDone() { return done; } - } - private boolean waitForCompletion(CompletableTask task) { - long waitTime = 0; - synchronized (task) { - while (!task.isDone() && waitTime < MAX_WAIT_TIME) { - try { - task.wait(WAIT_TIME_INCR); - waitTime += WAIT_TIME_INCR; - } catch (InterruptedException e) { - Log.i(TAG, "Interrupted during sleep", e); + public boolean waitForCompletion() { + long waitTime = 0; + synchronized (this) { + while (!isDone() && waitTime < MAX_WAIT_TIME) { + try { + wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } catch (InterruptedException e) { + Log.i(TAG, "Interrupted during sleep", e); + } } } - } - return task.isDone(); + return isDone(); + } } + private File getFilePath(String name) { final File filesDir = mContext.getFilesDir(); final File outFile = new File(filesDir, name); @@ -128,23 +136,52 @@ public class MountServiceTests extends AndroidTestCase { } private void mountObb(StorageManager sm, final int resource, final File file, - String expectedState) { + int expectedState) { copyRawToFile(resource, file); - ObbObserver observer = new ObbObserver(); + final ObbObserver observer = new ObbObserver(); assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file.getPath(), null, observer)); assertTrue("Mount should have completed", - waitForCompletion(observer)); + observer.waitForCompletion()); + + if (expectedState == OnObbStateChangeListener.MOUNTED) { + assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath())); + } assertEquals("Actual file and resolved file should be the same", - file.getPath(), observer.path); + file.getPath(), observer.getPath()); + + assertEquals(expectedState, observer.getState()); + } + + private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource, + final File file) { + copyRawToFile(resource, file); + + final ObbObserver observer = new ObbObserver(); + assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file + .getPath(), null, observer)); + + return observer; + } - assertEquals(expectedState, observer.state); + private void waitForObbActionCompletion(final StorageManager sm, final File file, + final ObbObserver observer, int expectedState, boolean checkPath) { + assertTrue("Mount should have completed", observer.waitForCompletion()); + + assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath())); + + if (checkPath) { + assertEquals("Actual file and resolved file should be the same", file.getPath(), + observer.getPath()); + } + + assertEquals(expectedState, observer.getState()); } - private String checkMountedPath(StorageManager sm, File file) { + private String checkMountedPath(final StorageManager sm, final File file) { final String mountPath = sm.getMountedObbPath(file.getPath()); assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX, OBB_MOUNT_PREFIX, @@ -152,13 +189,21 @@ public class MountServiceTests extends AndroidTestCase { return mountPath; } - private void unmountObb(StorageManager sm, final File outFile) { - ObbObserver observer = new ObbObserver(); + private void unmountObb(final StorageManager sm, final File file, int expectedState) { + final ObbObserver observer = new ObbObserver(); + assertTrue("unmountObb call on test1.obb should succeed", - sm.unmountObb(outFile.getPath(), false, observer)); + sm.unmountObb(file.getPath(), + false, observer)); assertTrue("Unmount should have completed", - waitForCompletion(observer)); + observer.waitForCompletion()); + + assertEquals(expectedState, observer.getState()); + + if (expectedState == OnObbStateChangeListener.UNMOUNTED) { + assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath())); + } } @LargeTest @@ -167,7 +212,9 @@ public class MountServiceTests extends AndroidTestCase { final File outFile = getFilePath("test1.obb"); - mountObb(sm, R.raw.test1, outFile, Environment.MEDIA_MOUNTED); + mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED); + + mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED); final String mountPath = checkMountedPath(sm, outFile); final File mountDir = new File(mountPath); @@ -175,7 +222,7 @@ public class MountServiceTests extends AndroidTestCase { assertTrue("OBB mounted path should be a directory", mountDir.isDirectory()); - unmountObb(sm, outFile); + unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED); } @LargeTest @@ -184,7 +231,7 @@ public class MountServiceTests extends AndroidTestCase { final File outFile = getFilePath("test1_nosig.obb"); - mountObb(sm, R.raw.test1_nosig, outFile, Environment.MEDIA_BAD_REMOVAL); + mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL); assertFalse("OBB should not be mounted", sm.isObbMounted(outFile.getPath())); @@ -199,7 +246,8 @@ public class MountServiceTests extends AndroidTestCase { final File outFile = getFilePath("test1_wrongpackage.obb"); - mountObb(sm, R.raw.test1_wrongpackage, outFile, Environment.MEDIA_BAD_REMOVAL); + mountObb(sm, R.raw.test1_wrongpackage, outFile, + OnObbStateChangeListener.ERROR_PERMISSION_DENIED); assertFalse("OBB should not be mounted", sm.isObbMounted(outFile.getPath())); @@ -207,4 +255,31 @@ public class MountServiceTests extends AndroidTestCase { assertNull("OBB's mounted path should be null", sm.getMountedObbPath(outFile.getPath())); } + + @LargeTest + public void testMountAndUnmountTwoObbs() { + StorageManager sm = getStorageManager(); + + final File file1 = getFilePath("test1.obb"); + final File file2 = getFilePath("test2.obb"); + + ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1); + ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2); + + Log.d(TAG, "Waiting for OBB #1 to complete mount"); + waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false); + Log.d(TAG, "Waiting for OBB #2 to complete mount"); + waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false); + + final String mountPath1 = checkMountedPath(sm, file1); + final File mountDir1 = new File(mountPath1); + assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory()); + + final String mountPath2 = checkMountedPath(sm, file2); + final File mountDir2 = new File(mountPath2); + assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory()); + + unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED); + unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED); + } } diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 76d5f4f..2b80342 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -279,12 +279,8 @@ </ul> </li> <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html"> - <span class="en">Device Administration</span></a> - <span class="new">new!</span> - </li> - <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html"> - <span class="en">Device Administration</span> - </a> <span class="new">new!</span><!-- 10/8/10 --> + <span class="en">Device Administration</span> + </a> <span class="new">new!</span> </li> </ul> </li> diff --git a/docs/html/guide/practices/design/responsiveness.jd b/docs/html/guide/practices/design/responsiveness.jd index b811d1b..a00e3aa 100644 --- a/docs/html/guide/practices/design/responsiveness.jd +++ b/docs/html/guide/practices/design/responsiveness.jd @@ -99,6 +99,10 @@ responsive to input and thus avoid ANR dialogs caused by the 5 second input event timeout. These same practices should be followed for any other threads that display UI, as they are also subject to the same timeouts.</p> +<p>You can use {@link android.os.StrictMode} to help find potentially +long running operations such as network or database operations that +you might accidentally be doing your main thread.</p> + <p>The specific constraint on IntentReceiver execution time emphasizes what they were meant to do: small, discrete amounts of work in the background such as saving a setting or registering a Notification. So as with other methods diff --git a/graphics/java/android/graphics/utils/BoundaryPatch.java b/graphics/java/android/graphics/utils/BoundaryPatch.java deleted file mode 100644 index 1cd5e13..0000000 --- a/graphics/java/android/graphics/utils/BoundaryPatch.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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.graphics.utils; - -import android.graphics.Bitmap; -import android.graphics.BitmapShader; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Shader; -import android.graphics.Xfermode; - -/** - * @hide - */ -public class BoundaryPatch { - private Paint mPaint; - private Bitmap mTexture; - private int mRows; - private int mCols; - private float[] mCubicPoints; - private boolean mDirty; - // these are the computed output of the native code - private float[] mVerts; - private short[] mIndices; - - public BoundaryPatch() { - mRows = mCols = 2; // default minimum - mCubicPoints = new float[24]; - mPaint = new Paint(); - mPaint.setDither(true); - mPaint.setFilterBitmap(true); - mDirty = true; - } - - /** - * Set the boundary to be 4 cubics. This takes a single array of floats, - * and picks up the 12 pairs starting at offset, and treats them as - * the x,y coordinates of the cubic control points. The points wrap around - * a patch, as follows. For documentation purposes, pts[i] will mean the - * x,y pair of floats, as if pts[] were an array of "points". - * - * Top: pts[0..3] - * Right: pts[3..6] - * Bottom: pts[6..9] - * Right: pts[9..11], pts[0] - * - * The coordinates are copied from the input array, so subsequent changes - * to pts[] will not be reflected in the boundary. - * - * @param pts The src array of x,y pairs for the boundary cubics - * @param offset The index into pts of the first pair - * @param rows The number of points across to approximate the boundary. - * Must be >= 2, though very large values may slow down drawing - * @param cols The number of points down to approximate the boundary. - * Must be >= 2, though very large values may slow down drawing - */ - public void setCubicBoundary(float[] pts, int offset, int rows, int cols) { - if (rows < 2 || cols < 2) { - throw new RuntimeException("rows and cols must be >= 2"); - } - System.arraycopy(pts, offset, mCubicPoints, 0, 24); - if (mRows != rows || mCols != cols) { - mRows = rows; - mCols = cols; - } - mDirty = true; - } - - /** - * Reference a bitmap texture to be mapped onto the patch. - */ - public void setTexture(Bitmap texture) { - if (mTexture != texture) { - if (mTexture == null || - mTexture.getWidth() != texture.getWidth() || - mTexture.getHeight() != texture.getHeight()) { - // need to recompute texture coordinates - mDirty = true; - } - mTexture = texture; - mPaint.setShader(new BitmapShader(texture, - Shader.TileMode.CLAMP, - Shader.TileMode.CLAMP)); - } - } - - /** - * Return the paint flags for the patch - */ - public int getPaintFlags() { - return mPaint.getFlags(); - } - - /** - * Set the paint flags for the patch - */ - public void setPaintFlags(int flags) { - mPaint.setFlags(flags); - } - - /** - * Set the xfermode for the patch - */ - public void setXfermode(Xfermode mode) { - mPaint.setXfermode(mode); - } - - /** - * Set the alpha for the patch - */ - public void setAlpha(int alpha) { - mPaint.setAlpha(alpha); - } - - /** - * Draw the patch onto the canvas. - * - * setCubicBoundary() and setTexture() must be called before drawing. - */ - public void draw(Canvas canvas) { - if (mDirty) { - buildCache(); - mDirty = false; - } - - // cut the count in half, since mVerts.length is really the length of - // the verts[] and tex[] arrays combined - // (tex[] are stored after verts[]) - int vertCount = mVerts.length >> 1; - canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertCount, - mVerts, 0, mVerts, vertCount, null, 0, - mIndices, 0, mIndices.length, - mPaint); - } - - private void buildCache() { - // we need mRows * mCols points, for verts and another set for textures - // so *2 for going from points -> floats, and *2 for verts and textures - int vertCount = mRows * mCols * 4; - if (mVerts == null || mVerts.length != vertCount) { - mVerts = new float[vertCount]; - } - - int indexCount = (mRows - 1) * (mCols - 1) * 6; - if (mIndices == null || mIndices.length != indexCount) { - mIndices = new short[indexCount]; - } - - nativeComputeCubicPatch(mCubicPoints, - mTexture.getWidth(), mTexture.getHeight(), - mRows, mCols, mVerts, mIndices); - } - - private static native - void nativeComputeCubicPatch(float[] cubicPoints, - int texW, int texH, int rows, int cols, - float[] verts, short[] indices); -} - diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java index 0f9ed87..97ce7dc 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -69,9 +69,22 @@ public class RenderScript { // Methods below are wrapped to protect the non-threadsafe // lockless fifo. - native int rsnContextCreateGL(int dev, int ver, boolean useDepth); - synchronized int nContextCreateGL(int dev, int ver, boolean useDepth) { - return rsnContextCreateGL(dev, ver, useDepth); + native int rsnContextCreateGL(int dev, int ver, + int colorMin, int colorPref, + int alphaMin, int alphaPref, + int depthMin, int depthPref, + int stencilMin, int stencilPref, + int samplesMin, int samplesPref, float samplesQ); + synchronized int nContextCreateGL(int dev, int ver, + int colorMin, int colorPref, + int alphaMin, int alphaPref, + int depthMin, int depthPref, + int stencilMin, int stencilPref, + int samplesMin, int samplesPref, float samplesQ) { + return rsnContextCreateGL(dev, ver, colorMin, colorPref, + alphaMin, alphaPref, depthMin, depthPref, + stencilMin, stencilPref, + samplesMin, samplesPref, samplesQ); } native int rsnContextCreate(int dev, int ver); synchronized int nContextCreate(int dev, int ver) { diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java index b60c689..0477d75 100644 --- a/graphics/java/android/renderscript/RenderScriptGL.java +++ b/graphics/java/android/renderscript/RenderScriptGL.java @@ -18,6 +18,7 @@ package android.renderscript; import java.lang.reflect.Field; +import android.graphics.PixelFormat; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Config; @@ -103,7 +104,11 @@ public class RenderScriptGL extends RenderScript { SurfaceConfig mSurfaceConfig; public void configureSurface(SurfaceHolder sh) { - //getHolder().setFormat(PixelFormat.TRANSLUCENT); + if (mSurfaceConfig.mAlphaMin > 1) { + sh.setFormat(PixelFormat.RGBA_8888); + } else { + sh.setFormat(PixelFormat.RGBX_8888); + } } public void checkSurface(SurfaceHolder sh) { @@ -112,13 +117,17 @@ public class RenderScriptGL extends RenderScript { public RenderScriptGL(SurfaceConfig sc) { mSurfaceConfig = new SurfaceConfig(sc); - - mSurface = null; mWidth = 0; mHeight = 0; mDev = nDeviceCreate(); - mContext = nContextCreateGL(mDev, 0, mSurfaceConfig.mDepthMin > 0); + mContext = nContextCreateGL(mDev, 0, + mSurfaceConfig.mColorMin, mSurfaceConfig.mColorPref, + mSurfaceConfig.mAlphaMin, mSurfaceConfig.mAlphaPref, + mSurfaceConfig.mDepthMin, mSurfaceConfig.mDepthPref, + mSurfaceConfig.mStencilMin, mSurfaceConfig.mStencilPref, + mSurfaceConfig.mSamplesMin, mSurfaceConfig.mSamplesPref, + mSurfaceConfig.mSamplesQ); mMessageThread = new MessageThread(this); mMessageThread.start(); Element.initPredefined(this); diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp index 014f03b..ce2a40c 100644 --- a/graphics/jni/android_renderscript_RenderScript.cpp +++ b/graphics/jni/android_renderscript_RenderScript.cpp @@ -158,10 +158,26 @@ nContextCreate(JNIEnv *_env, jobject _this, jint dev, jint ver) } static jint -nContextCreateGL(JNIEnv *_env, jobject _this, jint dev, jint ver, jboolean useDepth) -{ +nContextCreateGL(JNIEnv *_env, jobject _this, jint dev, jint ver, + int colorMin, int colorPref, + int alphaMin, int alphaPref, + int depthMin, int depthPref, + int stencilMin, int stencilPref, + int samplesMin, int samplesPref, float samplesQ) +{ + RsSurfaceConfig sc; + sc.alphaMin = alphaMin; + sc.alphaPref = alphaPref; + sc.colorMin = colorMin; + sc.colorPref = colorPref; + sc.depthMin = depthMin; + sc.depthPref = depthPref; + sc.samplesMin = samplesMin; + sc.samplesPref = samplesPref; + sc.samplesQ = samplesQ; + LOG_API("nContextCreateGL"); - return (jint)rsContextCreateGL((RsDevice)dev, ver, useDepth); + return (jint)rsContextCreateGL((RsDevice)dev, ver, sc); } static void @@ -309,7 +325,7 @@ nElementGetSubElements(JNIEnv *_env, jobject _this, RsContext con, jint id, jint rsElementGetSubElements(con, (RsElement)id, ids, names, (uint32_t)dataSize); - for(jint i = 0; i < dataSize; i ++) { + for(jint i = 0; i < dataSize; i++) { _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i])); _env->SetIntArrayRegion(_IDs, i, 1, (const jint*)&ids[i]); } @@ -1220,7 +1236,7 @@ static JNINativeMethod methods[] = { // All methods below are thread protected in java. {"rsnContextCreate", "(II)I", (void*)nContextCreate }, -{"rsnContextCreateGL", "(IIZ)I", (void*)nContextCreateGL }, +{"rsnContextCreateGL", "(IIIIIIIIIIIIF)I", (void*)nContextCreateGL }, {"rsnContextFinish", "(I)V", (void*)nContextFinish }, {"rsnContextSetPriority", "(II)V", (void*)nContextSetPriority }, {"rsnContextSetSurface", "(IIILandroid/view/Surface;)V", (void*)nContextSetSurface }, diff --git a/include/storage/IMountService.h b/include/storage/IMountService.h index 436fc38..51f9aeb 100644 --- a/include/storage/IMountService.h +++ b/include/storage/IMountService.h @@ -61,9 +61,9 @@ public: virtual void shutdown(const sp<IMountShutdownObserver>& observer) = 0; virtual void finishMediaUpdate() = 0; virtual void mountObb(const String16& filename, const String16& key, - const sp<IObbActionListener>& token) = 0; + const sp<IObbActionListener>& token, const int32_t nonce) = 0; virtual void unmountObb(const String16& filename, const bool force, - const sp<IObbActionListener>& token) = 0; + const sp<IObbActionListener>& token, const int32_t nonce) = 0; virtual bool isObbMounted(const String16& filename) = 0; virtual bool getMountedObbPath(const String16& filename, String16& path) = 0; }; diff --git a/include/storage/IObbActionListener.h b/include/storage/IObbActionListener.h index 1bedcc6..d78273c 100644 --- a/include/storage/IObbActionListener.h +++ b/include/storage/IObbActionListener.h @@ -29,7 +29,7 @@ class IObbActionListener: public IInterface public: DECLARE_META_INTERFACE(ObbActionListener); - virtual void onObbResult(const String16& filename, const String16& status) = 0; + virtual void onObbResult(const String16& filename, const int32_t nonce, const int32_t state) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index b181781..ac69a06 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -119,6 +119,8 @@ public: uint32_t* width, uint32_t* height, PixelFormat* format, uint32_t reqWidth, uint32_t reqHeight) = 0; + virtual status_t turnElectronBeamOff(int32_t mode) = 0; + /* Signal surfaceflinger that there might be some work to do * This is an ASYNCHRONOUS call. */ @@ -143,7 +145,8 @@ public: FREEZE_DISPLAY, UNFREEZE_DISPLAY, SIGNAL, - CAPTURE_SCREEN + CAPTURE_SCREEN, + TURN_ELECTRON_BEAM_OFF }; virtual status_t onTransact( uint32_t code, diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 8389e56..1b21aee 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -482,9 +482,9 @@ void FontRenderer::initVertexArrayBuffers() { } glGenBuffers(1, &mIndexBufferID); - glBindBuffer(GL_ARRAY_BUFFER, mIndexBufferID); - glBufferData(GL_ARRAY_BUFFER, indexBufferSizeBytes, indexBufferData, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSizeBytes, indexBufferData, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); free(indexBufferData); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 92875b1..2876010 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -455,7 +455,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, #endif // Clear the FBO - glScissor(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); + glScissor(0.0f, 0.0f, bounds.getWidth() + 1.0f, bounds.getHeight() + 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); @@ -585,7 +585,10 @@ void OpenGLRenderer::setMatrix(SkMatrix* matrix) { } const float* OpenGLRenderer::getMatrix() const { - return &mSnapshot->transform->data[0]; + if (mSnapshot->fbo != 0) { + return &mSnapshot->transform->data[0]; + } + return &mIdentity.data[0]; } void OpenGLRenderer::getMatrix(SkMatrix* matrix) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index f8828e2..423614b 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -432,6 +432,9 @@ private: // Misc GLint mMaxTextureSize; + // Indentity matrix + const mat4 mIdentity; + friend class DisplayListRenderer; }; // class OpenGLRenderer diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 1eac239..3cd85c8 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -417,7 +417,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti } // Optimization for common cases - if (!blendFramebuffer) { + if (!blendFramebuffer && description.colorOp == ProgramDescription::kColorNone) { bool fast = false; const bool noShader = !description.hasGradient && !description.hasBitmap; diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index ec9851e..9cb13b3 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -135,7 +135,7 @@ struct ProgramDescription { GLenum bitmapWrapT; // Color operations - int colorOp; + ColorModifier colorOp; SkXfermode::Mode colorMode; // Framebuffer blending (requires Extensions.hasFramebufferFetch()) diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h index f03a602..c571ea1 100644 --- a/libs/hwui/Rect.h +++ b/libs/hwui/Rect.h @@ -149,10 +149,10 @@ struct Rect { } void snapToPixelBoundaries() { - left = floor(left); - top = floor(top); - right = ceil(right); - bottom = ceil(bottom); + left = floorf(left); + top = floorf(top); + right = ceilf(right); + bottom = ceilf(bottom); } void dump() const { diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h index 66e27f3..da8edbe 100644 --- a/libs/rs/RenderScript.h +++ b/libs/rs/RenderScript.h @@ -55,12 +55,26 @@ enum RsDeviceParam { RS_DEVICE_PARAM_COUNT }; +typedef struct { + uint32_t colorMin; + uint32_t colorPref; + uint32_t alphaMin; + uint32_t alphaPref; + uint32_t depthMin; + uint32_t depthPref; + uint32_t stencilMin; + uint32_t stencilPref; + uint32_t samplesMin; + uint32_t samplesPref; + float samplesQ; +} RsSurfaceConfig; + RsDevice rsDeviceCreate(); void rsDeviceDestroy(RsDevice); void rsDeviceSetConfig(RsDevice, RsDeviceParam, int32_t value); RsContext rsContextCreate(RsDevice, uint32_t version); -RsContext rsContextCreateGL(RsDevice, uint32_t version, bool useDepth); +RsContext rsContextCreateGL(RsDevice, uint32_t version, RsSurfaceConfig sc); void rsContextDestroy(RsContext); uint32_t rsContextGetMessage(RsContext, void *data, size_t *receiveLen, size_t bufferLen, bool wait); @@ -270,6 +284,7 @@ typedef struct { } RsScriptCall; + #ifndef NO_RS_FUNCS #include "rsgApiFuncDecl.h" #endif diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 30add62..be8fb0e 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -18,6 +18,7 @@ #include "rsContext.h" #include "rsThreadIO.h" #include <ui/FramebufferNativeWindow.h> +#include <ui/PixelFormat.h> #include <ui/EGLUtils.h> #include <ui/egl/android_natives.h> @@ -56,8 +57,61 @@ static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { } } -void Context::initEGL(bool useGL2) +void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) { + +#define X(VAL) {VAL, #VAL} + struct {EGLint attribute; const char* name;} names[] = { + X(EGL_BUFFER_SIZE), + X(EGL_ALPHA_SIZE), + X(EGL_BLUE_SIZE), + X(EGL_GREEN_SIZE), + X(EGL_RED_SIZE), + X(EGL_DEPTH_SIZE), + X(EGL_STENCIL_SIZE), + X(EGL_CONFIG_CAVEAT), + X(EGL_CONFIG_ID), + X(EGL_LEVEL), + X(EGL_MAX_PBUFFER_HEIGHT), + X(EGL_MAX_PBUFFER_PIXELS), + X(EGL_MAX_PBUFFER_WIDTH), + X(EGL_NATIVE_RENDERABLE), + X(EGL_NATIVE_VISUAL_ID), + X(EGL_NATIVE_VISUAL_TYPE), + X(EGL_SAMPLES), + X(EGL_SAMPLE_BUFFERS), + X(EGL_SURFACE_TYPE), + X(EGL_TRANSPARENT_TYPE), + X(EGL_TRANSPARENT_RED_VALUE), + X(EGL_TRANSPARENT_GREEN_VALUE), + X(EGL_TRANSPARENT_BLUE_VALUE), + X(EGL_BIND_TO_TEXTURE_RGB), + X(EGL_BIND_TO_TEXTURE_RGBA), + X(EGL_MIN_SWAP_INTERVAL), + X(EGL_MAX_SWAP_INTERVAL), + X(EGL_LUMINANCE_SIZE), + X(EGL_ALPHA_MASK_SIZE), + X(EGL_COLOR_BUFFER_TYPE), + X(EGL_RENDERABLE_TYPE), + X(EGL_CONFORMANT), + }; +#undef X + + for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) { + EGLint value = -1; + EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); + EGLint error = eglGetError(); + if (returnVal && error == EGL_SUCCESS) { + LOGV(" %s: %d (0x%x)", names[j].name, value, value); + } + } +} + + +void Context::initGLThread() { + pthread_mutex_lock(&gInitMutex); + LOGV("initGLThread start %p", this); + mEGL.mNumConfigs = -1; EGLint configAttribs[128]; EGLint *configAttribsPtr = configAttribs; @@ -69,15 +123,13 @@ void Context::initEGL(bool useGL2) configAttribsPtr[1] = EGL_WINDOW_BIT; configAttribsPtr += 2; - if (useGL2) { - configAttribsPtr[0] = EGL_RENDERABLE_TYPE; - configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; - configAttribsPtr += 2; - } + configAttribsPtr[0] = EGL_RENDERABLE_TYPE; + configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; + configAttribsPtr += 2; - if (mUseDepth) { + if (mUserSurfaceConfig.depthMin > 0) { configAttribsPtr[0] = EGL_DEPTH_SIZE; - configAttribsPtr[1] = 16; + configAttribsPtr[1] = mUserSurfaceConfig.depthMin; configAttribsPtr += 2; } @@ -97,29 +149,94 @@ void Context::initEGL(bool useGL2) eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion); checkEglError("eglInitialize"); - status_t err = EGLUtils::selectConfigForNativeWindow(mEGL.mDisplay, configAttribs, mWndSurface, &mEGL.mConfig); +#if 1 + PixelFormat pf = PIXEL_FORMAT_RGBA_8888; + if (mUserSurfaceConfig.alphaMin == 0) { + pf = PIXEL_FORMAT_RGBX_8888; + } + + status_t err = EGLUtils::selectConfigForPixelFormat(mEGL.mDisplay, configAttribs, pf, &mEGL.mConfig); if (err) { LOGE("%p, couldn't find an EGLConfig matching the screen format\n", this); } - //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs); - - - if (useGL2) { - mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, context_attribs2); - } else { - mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL); + if (props.mLogVisual) { + printEGLConfiguration(mEGL.mDisplay, mEGL.mConfig); } +#else + eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs); +#endif + + mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, context_attribs2); checkEglError("eglCreateContext"); if (mEGL.mContext == EGL_NO_CONTEXT) { LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", this); } gGLContextCount++; + + + EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; + mEGL.mSurfaceDefault = eglCreatePbufferSurface(mEGL.mDisplay, mEGL.mConfig, pbuffer_attribs); + checkEglError("eglCreatePbufferSurface"); + if (mEGL.mSurfaceDefault == EGL_NO_SURFACE) { + LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE"); + } + + EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurfaceDefault, mEGL.mSurfaceDefault, mEGL.mContext); + checkEglError("eglMakeCurrent", ret); + + mGL.mVersion = glGetString(GL_VERSION); + mGL.mVendor = glGetString(GL_VENDOR); + mGL.mRenderer = glGetString(GL_RENDERER); + mGL.mExtensions = glGetString(GL_EXTENSIONS); + + //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); + LOGV("GL Version %s", mGL.mVersion); + //LOGV("GL Vendor %s", mGL.mVendor); + LOGV("GL Renderer %s", mGL.mRenderer); + //LOGV("GL Extensions %s", mGL.mExtensions); + + const char *verptr = NULL; + if (strlen((const char *)mGL.mVersion) > 9) { + if (!memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) { + verptr = (const char *)mGL.mVersion + 12; + } + if (!memcmp(mGL.mVersion, "OpenGL ES ", 10)) { + verptr = (const char *)mGL.mVersion + 9; + } + } + + if (!verptr) { + LOGE("Error, OpenGL ES Lite not supported"); + } else { + sscanf(verptr, " %i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion); + } + + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mGL.mMaxVertexAttribs); + glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &mGL.mMaxVertexUniformVectors); + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGL.mMaxVertexTextureUnits); + + glGetIntegerv(GL_MAX_VARYING_VECTORS, &mGL.mMaxVaryingVectors); + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGL.mMaxTextureImageUnits); + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mGL.mMaxFragmentTextureImageUnits); + glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors); + + mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot"); + mGL.EXT_texture_max_aniso = 1.0f; + bool hasAniso = NULL != strstr((const char *)mGL.mExtensions, "GL_EXT_texture_filter_anisotropic"); + if(hasAniso) { + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mGL.EXT_texture_max_aniso); + } + + LOGV("initGLThread end %p", this); + pthread_mutex_unlock(&gInitMutex); } void Context::deinitEGL() { LOGV("%p, deinitEGL", this); - setSurface(0, 0, NULL); + + eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, mEGL.mContext); eglDestroyContext(mEGL.mDisplay, mEGL.mContext); checkEglError("eglDestroyContext"); @@ -312,6 +429,8 @@ void * Context::threadProc(void *vrsc) LOGE("pthread_setspecific %i", status); } + rsc->initGLThread(); + rsc->mScriptC.init(rsc); if (rsc->mIsGraphicsContext) { rsc->mStateRaster.init(rsc); @@ -460,7 +579,7 @@ void Context::setPriority(int32_t p) #endif } -Context::Context(Device *dev, bool isGraphics, bool useDepth) +Context::Context(Device *dev, const RsSurfaceConfig *sc) { pthread_mutex_lock(&gInitMutex); @@ -468,15 +587,19 @@ Context::Context(Device *dev, bool isGraphics, bool useDepth) mDev = dev; mRunning = false; mExit = false; - mUseDepth = useDepth; mPaused = false; mObjHead = NULL; mError = RS_ERROR_NONE; mErrorMsg = NULL; + if (sc) { + mUserSurfaceConfig = *sc; + } else { + memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig)); + } memset(&mEGL, 0, sizeof(mEGL)); memset(&mGL, 0, sizeof(mGL)); - mIsGraphicsContext = isGraphics; + mIsGraphicsContext = sc != NULL; int status; pthread_attr_t threadAttr; @@ -490,6 +613,7 @@ Context::Context(Device *dev, bool isGraphics, bool useDepth) } } gThreadTLSKeyCount++; + pthread_mutex_unlock(&gInitMutex); // Global init done at this point. @@ -534,8 +658,6 @@ Context::Context(Device *dev, bool isGraphics, bool useDepth) break; } } - - pthread_attr_destroy(&threadAttr); } @@ -568,28 +690,21 @@ void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) EGLBoolean ret; if (mEGL.mSurface != NULL) { - ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurfaceDefault, mEGL.mSurfaceDefault, mEGL.mContext); checkEglError("eglMakeCurrent", ret); ret = eglDestroySurface(mEGL.mDisplay, mEGL.mSurface); checkEglError("eglDestroySurface", ret); mEGL.mSurface = NULL; - mWidth = 0; - mHeight = 0; + mWidth = 1; + mHeight = 1; } mWndSurface = sur; if (mWndSurface != NULL) { mWidth = w; mHeight = h; - bool first = false; - if (!mEGL.mContext) { - first = true; - pthread_mutex_lock(&gInitMutex); - initEGL(true); - pthread_mutex_unlock(&gInitMutex); - } mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL); checkEglError("eglCreateWindowSurface"); @@ -601,53 +716,6 @@ void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) checkEglError("eglMakeCurrent", ret); mStateVertex.updateSize(this); - - if (first) { - mGL.mVersion = glGetString(GL_VERSION); - mGL.mVendor = glGetString(GL_VENDOR); - mGL.mRenderer = glGetString(GL_RENDERER); - mGL.mExtensions = glGetString(GL_EXTENSIONS); - - //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); - LOGV("GL Version %s", mGL.mVersion); - //LOGV("GL Vendor %s", mGL.mVendor); - LOGV("GL Renderer %s", mGL.mRenderer); - //LOGV("GL Extensions %s", mGL.mExtensions); - - const char *verptr = NULL; - if (strlen((const char *)mGL.mVersion) > 9) { - if (!memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) { - verptr = (const char *)mGL.mVersion + 12; - } - if (!memcmp(mGL.mVersion, "OpenGL ES ", 10)) { - verptr = (const char *)mGL.mVersion + 9; - } - } - - if (!verptr) { - LOGE("Error, OpenGL ES Lite not supported"); - } else { - sscanf(verptr, " %i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion); - } - - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mGL.mMaxVertexAttribs); - glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &mGL.mMaxVertexUniformVectors); - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGL.mMaxVertexTextureUnits); - - glGetIntegerv(GL_MAX_VARYING_VECTORS, &mGL.mMaxVaryingVectors); - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGL.mMaxTextureImageUnits); - - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mGL.mMaxFragmentTextureImageUnits); - glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors); - - mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot"); - mGL.EXT_texture_max_aniso = 1.0f; - bool hasAniso = NULL != strstr((const char *)mGL.mExtensions, "GL_EXT_texture_filter_anisotropic"); - if(hasAniso) { - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mGL.EXT_texture_max_aniso); - } - } - } } @@ -829,7 +897,7 @@ void Context::dumpDebug() const LOGE(" GL Extensions: %s", mGL.mExtensions); LOGE(" GL int Versions %i %i", mGL.mMajorVersion, mGL.mMinorVersion); LOGE(" RS width %i, height %i", mWidth, mHeight); - LOGE(" RS running %i, exit %i, useDepth %i, paused %i", mRunning, mExit, mUseDepth, mPaused); + LOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused); LOGE(" RS pThreadID %li, nativeThreadID %i", mThreadId, mNativeThreadId); LOGV("MAX Textures %i, %i %i", mGL.mMaxVertexTextureUnits, mGL.mMaxFragmentTextureImageUnits, mGL.mMaxTextureImageUnits); @@ -957,15 +1025,15 @@ RsContext rsContextCreate(RsDevice vdev, uint32_t version) { LOGV("rsContextCreate %p", vdev); Device * dev = static_cast<Device *>(vdev); - Context *rsc = new Context(dev, false, false); + Context *rsc = new Context(dev, NULL); return rsc; } -RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, bool useDepth) +RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, RsSurfaceConfig sc) { - LOGV("rsContextCreateGL %p, %i", vdev, useDepth); + LOGV("rsContextCreateGL %p", vdev); Device * dev = static_cast<Device *>(vdev); - Context *rsc = new Context(dev, true, useDepth); + Context *rsc = new Context(dev, &sc); LOGV("rsContextCreateGL ret %p ", rsc); return rsc; } diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index 8a8b8a8..dbe2c79 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -69,7 +69,7 @@ namespace renderscript { class Context { public: - Context(Device *, bool isGraphics, bool useDepth); + Context(Device *, const RsSurfaceConfig *sc); ~Context(); static pthread_key_t gThreadTLSKey; @@ -82,6 +82,7 @@ public: Script * mScript; }; ScriptTLSStruct *mTlsStruct; + RsSurfaceConfig mUserSurfaceConfig; typedef void (*WorkerCallback_t)(void *usr, uint32_t idx); @@ -207,6 +208,7 @@ protected: EGLConfig mConfig; EGLContext mContext; EGLSurface mSurface; + EGLSurface mSurfaceDefault; EGLDisplay mDisplay; } mEGL; @@ -240,7 +242,6 @@ protected: bool mRunning; bool mExit; - bool mUseDepth; bool mPaused; RsError mError; const char *mErrorMsg; @@ -274,7 +275,8 @@ protected: private: Context(); - void initEGL(bool useGL2); + void initEGL(); + void initGLThread(); void deinitEGL(); uint32_t runRootScript(); diff --git a/libs/rs/rsProgramStore.cpp b/libs/rs/rsProgramStore.cpp index 3f90d7a..586a89f 100644 --- a/libs/rs/rsProgramStore.cpp +++ b/libs/rs/rsProgramStore.cpp @@ -76,14 +76,25 @@ void ProgramStore::setupGL2(const Context *rsc, ProgramStoreState *state) //LOGE("pfs %i, %i, %x", mDepthWriteEnable, mDepthTestEnable, mDepthFunc); - glDepthMask(mDepthWriteEnable); - if(mDepthTestEnable || mDepthWriteEnable) { - glEnable(GL_DEPTH_TEST); - glDepthFunc(mDepthFunc); + if (rsc->mUserSurfaceConfig.depthMin > 0) { + glDepthMask(mDepthWriteEnable); + if(mDepthTestEnable || mDepthWriteEnable) { + glEnable(GL_DEPTH_TEST); + glDepthFunc(mDepthFunc); + } else { + glDisable(GL_DEPTH_TEST); + } } else { + glDepthMask(false); glDisable(GL_DEPTH_TEST); } + if (rsc->mUserSurfaceConfig.stencilMin > 0) { + } else { + glStencilMask(0); + glDisable(GL_STENCIL_TEST); + } + if (mDitherEnable) { glEnable(GL_DITHER); } else { diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp index 17a961b..b5f9c47 100644 --- a/libs/storage/IMountService.cpp +++ b/libs/storage/IMountService.cpp @@ -431,13 +431,14 @@ public: } void mountObb(const String16& filename, const String16& key, - const sp<IObbActionListener>& token) + const sp<IObbActionListener>& token, int32_t nonce) { Parcel data, reply; data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); data.writeString16(filename); data.writeString16(key); data.writeStrongBinder(token->asBinder()); + data.writeInt32(nonce); if (remote()->transact(TRANSACTION_mountObb, data, &reply) != NO_ERROR) { LOGD("mountObb could not contact remote\n"); return; @@ -449,12 +450,15 @@ public: } } - void unmountObb(const String16& filename, const bool force, const sp<IObbActionListener>& token) + void unmountObb(const String16& filename, const bool force, + const sp<IObbActionListener>& token, const int32_t nonce) { Parcel data, reply; data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); data.writeString16(filename); data.writeInt32(force ? 1 : 0); + data.writeStrongBinder(token->asBinder()); + data.writeInt32(nonce); if (remote()->transact(TRANSACTION_unmountObb, data, &reply) != NO_ERROR) { LOGD("unmountObb could not contact remote\n"); return; diff --git a/libs/storage/IObbActionListener.cpp b/libs/storage/IObbActionListener.cpp index 5bfece7..eaa211e 100644 --- a/libs/storage/IObbActionListener.cpp +++ b/libs/storage/IObbActionListener.cpp @@ -30,7 +30,7 @@ public: : BpInterface<IObbActionListener>(impl) { } - virtual void onObbResult(const String16& filename, const String16& status) { } + virtual void onObbResult(const String16& filename, const int32_t nonce, const int32_t state) { } }; IMPLEMENT_META_INTERFACE(ObbActionListener, "IObbActionListener"); @@ -44,8 +44,9 @@ status_t BnObbActionListener::onTransact( case TRANSACTION_onObbResult: { CHECK_INTERFACE(IObbActionListener, data, reply); String16 filename = data.readString16(); - String16 state = data.readString16(); - onObbResult(filename, state); + int32_t nonce = data.readInt32(); + int32_t state = data.readInt32(); + onObbResult(filename, nonce, state); reply->writeNoException(); return NO_ERROR; } break; diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp index d676f5e..d72561f 100644 --- a/libs/surfaceflinger_client/ISurfaceComposer.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp @@ -142,6 +142,15 @@ public: return reply.readInt32(); } + virtual status_t turnElectronBeamOff(int32_t mode) + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeInt32(mode); + remote()->transact(BnSurfaceComposer::TURN_ELECTRON_BEAM_OFF, data, &reply); + return reply.readInt32(); + } + virtual void signal() const { Parcel data, reply; @@ -224,6 +233,12 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(f); reply->writeInt32(res); } break; + case TURN_ELECTRON_BEAM_OFF: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t mode = data.readInt32(); + status_t res = turnElectronBeamOff(mode); + reply->writeInt32(res); + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index 52e488a..84c3db8 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -432,10 +432,9 @@ void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropR switch (dropReason) { case DROP_REASON_POLICY: #if DEBUG_INBOUND_EVENT_DETAILS - LOGD("Dropped event because policy requested that it not be delivered to the application."); + LOGD("Dropped event because policy consumed it."); #endif - reason = "inbound event was dropped because the policy requested that it not be " - "delivered to the application"; + reason = "inbound event was dropped because the policy consumed it"; break; case DROP_REASON_DISABLED: LOGI("Dropped event because input dispatch is disabled."); @@ -625,15 +624,13 @@ bool InputDispatcher::dispatchKeyLocked( if (*dropReason == DROP_REASON_NOT_DROPPED) { *dropReason = DROP_REASON_POLICY; } - resetTargetsLocked(); - setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED); - return true; } // Clean up if dropping the event. if (*dropReason != DROP_REASON_NOT_DROPPED) { resetTargetsLocked(); - setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); + setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY + ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED); return true; } @@ -713,7 +710,8 @@ bool InputDispatcher::dispatchMotionLocked( // Clean up if dropping the event. if (*dropReason != DROP_REASON_NOT_DROPPED) { resetTargetsLocked(); - setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); + setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY + ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED); return true; } @@ -3396,7 +3394,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim } } - for (size_t i = 0; i < mMotionMementos.size(); i++) { + for (size_t i = 0; i < mMotionMementos.size(); ) { const MotionMemento& memento = mMotionMementos.itemAt(i); if (shouldCancelEvent(memento.source, options)) { outEvents.push(allocator->obtainMotionEntry(currentTime, diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp index 2f20641..a4233e7 100644 --- a/native/android/storage_manager.cpp +++ b/native/android/storage_manager.cpp @@ -21,10 +21,13 @@ #include <binder/Binder.h> #include <binder/IServiceManager.h> +#include <utils/Atomic.h> #include <utils/Log.h> #include <utils/RefBase.h> #include <utils/String8.h> #include <utils/String16.h> +#include <utils/Vector.h> +#include <utils/threads.h> using namespace android; @@ -38,20 +41,46 @@ public: mStorageManager(mgr) {} - virtual void onObbResult(const android::String16& filename, const android::String16& state); + virtual void onObbResult(const android::String16& filename, const int32_t nonce, + const int32_t state); +}; + +class ObbCallback { +public: + ObbCallback(int32_t _nonce, AStorageManager_obbCallbackFunc _cb, void* _data) + : nonce(_nonce) + , cb(_cb) + , data(_data) + {} + + int32_t nonce; + AStorageManager_obbCallbackFunc cb; + void* data; }; struct AStorageManager : public RefBase { protected: - AStorageManager_obbCallbackFunc mObbCallback; - void* mObbCallbackData; + Mutex mCallbackLock; + Vector<ObbCallback*> mCallbacks; + volatile int32_t mNextNonce; sp<ObbActionListener> mObbActionListener; sp<IMountService> mMountService; + int32_t getNextNonce() { + return android_atomic_inc(&mNextNonce); + } + + ObbCallback* registerObbCallback(AStorageManager_obbCallbackFunc func, void* data) { + ObbCallback* cb = new ObbCallback(getNextNonce(), func, data); + { + AutoMutex _l(mCallbackLock); + mCallbacks.push(cb); + } + return cb; + } + public: AStorageManager() - : mObbCallback(NULL) - , mObbCallbackData(NULL) { } @@ -73,26 +102,40 @@ public: return true; } - void setObbCallback(AStorageManager_obbCallbackFunc cb, void* data) { - mObbCallback = cb; - mObbCallbackData = data; - } + void fireCallback(const char* filename, const int32_t nonce, const int32_t state) { + ObbCallback* target = NULL; + { + AutoMutex _l(mCallbackLock); + int N = mCallbacks.size(); + for (int i = 0; i < N; i++) { + ObbCallback* cb = mCallbacks.editItemAt(i); + if (cb->nonce == nonce) { + target = cb; + mCallbacks.removeAt(i); + break; + } + } + } - void fireCallback(const char* filename, const char* state) { - if (mObbCallback != NULL) { - mObbCallback(filename, state, mObbCallbackData); + if (target != NULL) { + target->cb(filename, state, target->data); + delete target; + } else { + LOGI("Didn't find the callback handler for: %s\n", filename); } } - void mountObb(const char* filename, const char* key) { + void mountObb(const char* filename, const char* key, AStorageManager_obbCallbackFunc func, void* data) { + ObbCallback* cb = registerObbCallback(func, data); String16 filename16(filename); String16 key16(key); - mMountService->mountObb(filename16, key16, mObbActionListener); + mMountService->mountObb(filename16, key16, mObbActionListener, cb->nonce); } - void unmountObb(const char* filename, const bool force) { + void unmountObb(const char* filename, const bool force, AStorageManager_obbCallbackFunc func, void* data) { + ObbCallback* cb = registerObbCallback(func, data); String16 filename16(filename); - mMountService->unmountObb(filename16, force, mObbActionListener); + mMountService->unmountObb(filename16, force, mObbActionListener, cb->nonce); } int isObbMounted(const char* filename) { @@ -111,8 +154,8 @@ public: } }; -void ObbActionListener::onObbResult(const android::String16& filename, const android::String16& state) { - mStorageManager->fireCallback(String8(filename).string(), String8(state).string()); +void ObbActionListener::onObbResult(const android::String16& filename, const int32_t nonce, const int32_t state) { + mStorageManager->fireCallback(String8(filename).string(), nonce, state); } @@ -131,16 +174,14 @@ void AStorageManager_delete(AStorageManager* mgr) { } } -void AStorageManager_setObbCallback(AStorageManager* mgr, AStorageManager_obbCallbackFunc cb, void* data) { - mgr->setObbCallback(cb, data); -} - -void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key) { - mgr->mountObb(filename, key); +void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key, + AStorageManager_obbCallbackFunc cb, void* data) { + mgr->mountObb(filename, key, cb, data); } -void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force) { - mgr->unmountObb(filename, force != 0); +void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force, + AStorageManager_obbCallbackFunc cb, void* data) { + mgr->unmountObb(filename, force != 0, cb, data); } int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename) { diff --git a/native/include/android/storage_manager.h b/native/include/android/storage_manager.h index 6f925c1..c202693 100644 --- a/native/include/android/storage_manager.h +++ b/native/include/android/storage_manager.h @@ -18,6 +18,8 @@ #ifndef ANDROID_STORAGE_MANAGER_H #define ANDROID_STORAGE_MANAGER_H +#include <stdint.h> + #ifdef __cplusplus extern "C" { #endif @@ -25,6 +27,60 @@ extern "C" { struct AStorageManager; typedef struct AStorageManager AStorageManager; +enum { + /* + * The OBB container is now mounted and ready for use. Can be returned + * as the status for callbacks made during asynchronous OBB actions. + */ + AOBB_STATE_MOUNTED = 1, + + /* + * The OBB container is now unmounted and not usable. Can be returned + * as the status for callbacks made during asynchronous OBB actions. + */ + AOBB_STATE_UNMOUNTED = 2, + + /* + * There was an internal system error encountered while trying to + * mount the OBB. Can be returned as the status for callbacks made + * during asynchronous OBB actions. + */ + AOBB_STATE_ERROR_INTERNAL = 20, + + /* + * The OBB could not be mounted by the system. Can be returned as the + * status for callbacks made during asynchronous OBB actions. + */ + AOBB_STATE_ERROR_COULD_NOT_MOUNT = 21, + + /* + * The OBB could not be unmounted. This most likely indicates that a + * file is in use on the OBB. Can be returned as the status for + * callbacks made during asynchronous OBB actions. + */ + AOBB_STATE_ERROR_COULD_NOT_UNMOUNT = 22, + + /* + * A call was made to unmount the OBB when it was not mounted. Can be + * returned as the status for callbacks made during asynchronous OBB + * actions. + */ + AOBB_STATE_ERROR_NOT_MOUNTED = 23, + + /* + * The OBB has already been mounted. Can be returned as the status for + * callbacks made during asynchronous OBB actions. + */ + AOBB_STATE_ERROR_ALREADY_MOUNTED = 24, + + /* + * The current application does not have permission to use this OBB + * because the OBB indicates it's owned by a different package or the + * key used to open it is incorrect. Can be returned as the status for + * callbacks made during asynchronous OBB actions. + */ + AOBB_STATE_ERROR_PERMISSION_DENIED = 25, +}; /** * Obtains a new instance of AStorageManager. @@ -39,22 +95,19 @@ void AStorageManager_delete(AStorageManager* mgr); /** * Callback function for asynchronous calls made on OBB files. */ -typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const char* state, void* data); - -/** - * Callback to call when requested asynchronous OBB operation is complete. - */ -void AStorageManager_setObbCallback(AStorageManager* mgr, AStorageManager_obbCallbackFunc cb, void* data); +typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const int32_t state, void* data); /** * Attempts to mount an OBB file. This is an asynchronous operation. */ -void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key); +void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key, + AStorageManager_obbCallbackFunc cb, void* data); /** * Attempts to unmount an OBB file. This is an asynchronous operation. */ -void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force); +void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force, + AStorageManager_obbCallbackFunc cb, void* data); /** * Check whether an OBB is mounted. diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 6057023..5fde3c3 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -28,6 +28,10 @@ <activity android:name=".usb.UsbStorageActivity" android:excludeFromRecents="true"> </activity> + <activity android:name="com.android.internal.app.ExternalMediaFormatActivity" + android:theme="@*android:style/Theme.Dialog.Alert" + android:excludeFromRecents="true"> + </activity> <activity android:name=".recent.RecentApplicationsActivity" android:theme="@android:style/Theme.NoTitleBar" diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml index 494dfa8..295c79b 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml @@ -144,6 +144,7 @@ android:paddingLeft="4dip" android:paddingRight="4dip" systemui:keyCode="82" + android:visibility="invisible" /> <ImageButton android:id="@+id/recent" android:layout_width="wrap_content" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 81091e3..c164eb4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -54,6 +54,8 @@ public class CommandQueue extends IStatusBar.Stub { private static final int MSG_SET_LIGHTS_ON = 0x00070000; + private static final int MSG_SHOW_MENU = 0x00080000; + private StatusBarIconList mList; private Callbacks mCallbacks; private Handler mHandler = new H(); @@ -78,6 +80,7 @@ public class CommandQueue extends IStatusBar.Stub { public void animateExpand(); public void animateCollapse(); public void setLightsOn(boolean on); + public void setMenuKeyVisible(boolean visible); } public CommandQueue(Callbacks callbacks, StatusBarIconList list) { @@ -153,6 +156,13 @@ public class CommandQueue extends IStatusBar.Stub { } } + public void setMenuKeyVisible(boolean visible) { + synchronized (mList) { + mHandler.removeMessages(MSG_SHOW_MENU); + mHandler.obtainMessage(MSG_SHOW_MENU, visible ? 1 : 0, 0, null).sendToTarget(); + } + } + private final class H extends Handler { public void handleMessage(Message msg) { final int what = msg.what & MSG_MASK; @@ -210,6 +220,9 @@ public class CommandQueue extends IStatusBar.Stub { case MSG_SET_LIGHTS_ON: mCallbacks.setLightsOn(msg.arg1 != 0); break; + case MSG_SHOW_MENU: + mCallbacks.setMenuKeyVisible(msg.arg1 != 0); + break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java index 1e89624..2f94af6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java @@ -23,12 +23,22 @@ import android.view.MotionEvent; import android.widget.FrameLayout; public class LatestItemView extends FrameLayout { + private boolean mDispatchTorches; public LatestItemView(Context context, AttributeSet attrs) { super(context, attrs); } public boolean dispatchTouchEvent(MotionEvent ev) { - return onTouchEvent(ev); + if (mDispatchTorches) { + return super.dispatchTouchEvent(ev); + } else { + return onTouchEvent(ev); + } + } + + public void setOnClickListener(OnClickListener l) { + mDispatchTorches = l == null; + super.setOnClickListener(l); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java index 57ebd27..fc7b534 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java @@ -440,6 +440,8 @@ public class PhoneStatusBarService extends StatusBarService { if (contentIntent != null) { oldEntry.content.setOnClickListener(new Launcher(contentIntent, notification.pkg, notification.tag, notification.id)); + } else { + oldEntry.content.setOnClickListener(null); } // Update the icon. final StatusBarIcon ic = new StatusBarIcon(notification.pkg, @@ -516,6 +518,8 @@ public class PhoneStatusBarService extends StatusBarService { if (contentIntent != null) { content.setOnClickListener(new Launcher(contentIntent, notification.pkg, notification.tag, notification.id)); + } else { + content.setOnClickListener(null); } View expanded = null; @@ -1013,6 +1017,9 @@ public class PhoneStatusBarService extends StatusBarService { } } + // Not supported + public void setMenuKeyVisible(boolean visible) { } + private class Launcher implements View.OnClickListener { private PendingIntent mIntent; private String mPkg; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java index 695fdba..5594a47 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java @@ -72,15 +72,16 @@ public abstract class StatusBarService extends Service implements CommandQueue.C mCommandQueue = new CommandQueue(this, iconList); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); - boolean[] lightsOn = new boolean[1]; + boolean[] switches = new boolean[2]; try { mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications, - lightsOn); + switches); } catch (RemoteException ex) { // If the system process isn't there we're doomed anyway. } - setLightsOn(lightsOn[0]); + setLightsOn(switches[0]); + setMenuKeyVisible(switches[1]); // Set up the initial icon state int N = iconList.size(); @@ -120,7 +121,11 @@ public abstract class StatusBarService extends Service implements CommandQueue.C // TODO lp.windowAnimations = R.style.Animation_StatusBar; WindowManagerImpl.getDefault().addView(sb, lp); - Slog.d(TAG, "Added status bar view w/ gravity 0x" + Integer.toHexString(lp.gravity)); + Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity) + + " icons=" + iconList.size() + + " lights=" + (switches[0]?"on":"off") + + " menu=" + (switches[1]?"visible":"invisible") + ); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java index 0e26f52..340e269 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java @@ -79,6 +79,7 @@ public class TabletStatusBarService extends StatusBarService { View mNotificationButtons; View mSystemInfo; View mNavigationArea; + View mMenuButton; NotificationPanel mNotificationPanel; SystemPanel mSystemPanel; @@ -205,6 +206,7 @@ public class TabletStatusBarService extends StatusBarService { // The navigation buttons mNavigationArea = sb.findViewById(R.id.navigationArea); + mMenuButton = mNavigationArea.findViewById(R.id.menu); // set the initial view visibility setAreThereNotifications(); @@ -370,6 +372,8 @@ public class TabletStatusBarService extends StatusBarService { if (contentIntent != null) { oldEntry.content.setOnClickListener(new NotificationClicker(contentIntent, notification.pkg, notification.tag, notification.id)); + } else { + oldEntry.content.setOnClickListener(null); } // Update the icon. final StatusBarIcon ic = new StatusBarIcon(notification.pkg, @@ -503,6 +507,15 @@ public class TabletStatusBarService extends StatusBarService { } } + public void setMenuKeyVisible(boolean visible) { + if (DEBUG) { + Slog.d(TAG, (visible?"showing":"hiding") + " the MENU button"); + } + setViewVisibility(mMenuButton, + visible ? View.VISIBLE : View.INVISIBLE, + visible ? R.anim.navigation_in : R.anim.navigation_out); + } + private void setAreThereNotifications() { final boolean hasClearable = mNotns.hasClearableItems(); @@ -760,6 +773,8 @@ public class TabletStatusBarService extends StatusBarService { if (contentIntent != null) { content.setOnClickListener(new NotificationClicker(contentIntent, sbn.pkg, sbn.tag, sbn.id)); + } else { + content.setOnClickListener(null); } View expanded = null; diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index b9e915a4..47ed7da 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -16,33 +16,17 @@ package com.android.systemui.usb; -import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; import android.content.res.Resources; -import android.os.Bundle; import android.os.Environment; -import android.os.Handler; -import android.os.storage.IMountService; -import android.os.Message; -import android.os.ServiceManager; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; -import android.os.storage.StorageResultCode; import android.provider.Settings; import android.util.Slog; -import android.view.View; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; public class StorageNotification extends StorageEventListener { private static final String TAG = "StorageNotification"; @@ -165,10 +149,16 @@ public class StorageNotification extends StorageEventListener { * Show safe to unmount media notification, and enable UMS * notification if connected. */ - setMediaStorageNotification( - com.android.internal.R.string.ext_media_safe_unmount_notification_title, - com.android.internal.R.string.ext_media_safe_unmount_notification_message, - com.android.internal.R.drawable.stat_notify_sdcard, true, true, null); + if (Environment.isExternalStorageRemovable()) { + setMediaStorageNotification( + com.android.internal.R.string.ext_media_safe_unmount_notification_title, + com.android.internal.R.string.ext_media_safe_unmount_notification_message, + com.android.internal.R.drawable.stat_notify_sdcard, true, true, null); + } else { + // This device does not have removable storage, so + // don't tell the user they can remove it. + setMediaStorageNotification(0, 0, 0, false, false, null); + } updateUsbMassStorageNotification(mUmsAvailable); } } else { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 24c9443..db5f6c1 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; +import static android.view.WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY; import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; @@ -2324,6 +2325,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags())); } + if (getContext().getApplicationInfo().targetSdkVersion + < android.os.Build.VERSION_CODES.HONEYCOMB) { + addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY); + } + WindowManager.LayoutParams params = getAttributes(); if (!hasSoftInputMode()) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 449bd4c..c6898d4 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -287,6 +287,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { Intent mDeskDockIntent; boolean mSearchKeyPressed; boolean mConsumeSearchKeyUp; + boolean mShowMenuKey = false; // track FLAG_NEEDS_MENU_KEY on frontmost window // support for activating the lock screen while the screen is on boolean mAllowLockscreenWhenOn; @@ -1123,10 +1124,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, int keyCode, int metaState, int repeatCount, int policyFlags) { - if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) { - return false; - } - final boolean keyguardOn = keyguardOn(); final boolean down = (action == KeyEvent.ACTION_DOWN); final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0); @@ -1603,8 +1600,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public int finishAnimationLw() { int changes = 0; - boolean topIsFullscreen = false; + + final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) + ? mTopFullscreenOpaqueWindowState.getAttrs() + : null; + if (mStatusBar != null) { if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar + " top=" + mTopFullscreenOpaqueWindowState); @@ -1612,7 +1613,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar"); if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; } else if (mTopFullscreenOpaqueWindowState != null) { - final WindowManager.LayoutParams lp = mTopFullscreenOpaqueWindowState.getAttrs(); if (localLOGV) { Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw()); @@ -1637,10 +1637,26 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - - if (topIsFullscreen != mTopIsFullscreen) { + + boolean topNeedsMenu = mShowMenuKey; + if (lp != null) { + topNeedsMenu = (lp.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; + } + + if (DEBUG_LAYOUT) Log.v(TAG, "Top window " + + (topNeedsMenu ? "needs" : "does not need") + + " the MENU key"); + + final boolean changedFullscreen = (mTopIsFullscreen != topIsFullscreen); + final boolean changedMenu = (topNeedsMenu != mShowMenuKey); + + if (changedFullscreen || changedMenu) { final boolean topIsFullscreenF = topIsFullscreen; + final boolean topNeedsMenuF = topNeedsMenu; + mTopIsFullscreen = topIsFullscreen; + mShowMenuKey = topNeedsMenu; + mHandler.post(new Runnable() { public void run() { if (mStatusBarService == null) { @@ -1654,7 +1670,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { final IStatusBarService sbs = mStatusBarService; if (mStatusBarService != null) { try { - sbs.setActiveWindowIsFullscreen(topIsFullscreenF); + if (changedFullscreen) { + sbs.setActiveWindowIsFullscreen(topIsFullscreenF); + } + if (changedMenu) { + sbs.setMenuKeyVisible(topNeedsMenuF); + } } catch (RemoteException e) { // This should be impossible because we're in the same process. mStatusBarService = null; @@ -1835,9 +1856,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, int policyFlags, boolean isScreenOn) { int result = ACTION_PASS_TO_USER; - if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) { - return result; - } if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) { performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); @@ -1845,7 +1863,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; - + + // If the key is injected, pretend that the screen is on and don't let the + // device go to sleep. This feature is mainly used for testing purposes. + final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; + if (isInjected) { + isScreenOn = true; + } + // If screen is off then we treat the case where the keyguard is open but hidden // the same as if it were open and in front. // This will prevent any keys other than the power button from waking the screen @@ -1944,7 +1969,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { || (handled && hungUp && keyCode == KeyEvent.KEYCODE_POWER)) { mShouldTurnOffOnKeyUp = false; } else { - // only try to turn off the screen if we didn't already hang up + // Only try to turn off the screen if we didn't already hang up. mShouldTurnOffOnKeyUp = true; mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()); @@ -1967,12 +1992,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (keyguardActive || (sleeps && !gohome) || (gohome && !goHome() && sleeps)) { - // they must already be on the keyguad or home screen, - // go to sleep instead - Log.d(TAG, "I'm tired mEndcallBehavior=0x" - + Integer.toHexString(mEndcallBehavior)); - result &= ~ACTION_POKE_USER_ACTIVITY; - result |= ACTION_GO_TO_SLEEP; + // They must already be on the keyguard or home screen, + // go to sleep instead unless the event was injected. + if (!isInjected) { + Log.d(TAG, "I'm tired mEndcallBehavior=0x" + + Integer.toHexString(mEndcallBehavior)); + result &= ~ACTION_POKE_USER_ACTIVITY; + result |= ACTION_GO_TO_SLEEP; + } } result &= ~ACTION_PASS_TO_USER; } diff --git a/preloaded-classes b/preloaded-classes index ee82a2c..21c5df8 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -254,7 +254,6 @@ android.graphics.drawable.StateListDrawable android.graphics.drawable.StateListDrawable$StateListState android.graphics.drawable.TransitionDrawable android.graphics.drawable.TransitionDrawable$TransitionState -android.graphics.utils.BoundaryPatch android.hardware.Camera android.hardware.Camera$Parameters android.hardware.GeomagneticField diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index baa5016..f8611e4 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -44,6 +44,7 @@ import android.os.storage.IMountService; import android.os.storage.IMountServiceListener; import android.os.storage.IMountShutdownObserver; import android.os.storage.IObbActionListener; +import android.os.storage.OnObbStateChangeListener; import android.os.storage.StorageResultCode; import android.security.MessageDigest; import android.util.Slog; @@ -53,7 +54,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -163,25 +163,25 @@ class MountService extends IMountService.Stub final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>(); class ObbState implements IBinder.DeathRecipient { - public ObbState(String filename, IObbActionListener token, int callerUid) + public ObbState(String filename, int callerUid, IObbActionListener token, int nonce) throws RemoteException { this.filename = filename; - this.token = token; this.callerUid = callerUid; - mounted = false; + this.token = token; + this.nonce = nonce; } // OBB source filename - final String filename; - - // Token of remote Binder caller - final IObbActionListener token; + String filename; // Binder.callingUid() final public int callerUid; - // Whether this is mounted currently. - boolean mounted; + // Token of remote Binder caller + final IObbActionListener token; + + // Identifier to pass back to the token + final int nonce; public IBinder getBinder() { return token.asBinder(); @@ -210,8 +210,6 @@ class MountService extends IMountService.Stub sb.append(token.toString()); sb.append(",callerUid="); sb.append(callerUid); - sb.append(",mounted="); - sb.append(mounted); sb.append('}'); return sb.toString(); } @@ -225,6 +223,7 @@ class MountService extends IMountService.Stub private static final int OBB_MCS_BOUND = 2; private static final int OBB_MCS_UNBIND = 3; private static final int OBB_MCS_RECONNECT = 4; + private static final int OBB_FLUSH_MOUNT_STATE = 5; /* * Default Container Service information @@ -508,38 +507,19 @@ class MountService extends IMountService.Stub if (!mEmulateExternalStorage) { if (Environment.MEDIA_UNMOUNTED.equals(state)) { mPms.updateExternalMediaStatus(false, false); + + /* + * Some OBBs might have been unmounted when this volume was + * unmounted, so send a message to the handler to let it know to + * remove those from the list of mounted OBBS. + */ + mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_FLUSH_MOUNT_STATE, + path)); } else if (Environment.MEDIA_MOUNTED.equals(state)) { mPms.updateExternalMediaStatus(true, false); } } - // Remove all OBB mappings and listeners from this path - synchronized (mObbMounts) { - final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>(); - - final Iterator<Entry<String, ObbState>> i = mObbPathToStateMap.entrySet().iterator(); - while (i.hasNext()) { - final Entry<String, ObbState> obbEntry = i.next(); - - // If this entry's source file is in the volume path that got - // unmounted, remove it because it's no longer valid. - if (obbEntry.getKey().startsWith(path)) { - obbStatesToRemove.add(obbEntry.getValue()); - } - } - - for (final ObbState obbState : obbStatesToRemove) { - removeObbState(obbState); - - try { - obbState.token.onObbResult(obbState.filename, Environment.MEDIA_UNMOUNTED); - } catch (RemoteException e) { - Slog.i(TAG, "Couldn't send unmount notification for OBB: " - + obbState.filename); - } - } - } - String oldState = mLegacyState; mLegacyState = state; @@ -1547,6 +1527,10 @@ class MountService extends IMountService.Stub } public String getMountedObbPath(String filename) { + if (filename == null) { + throw new IllegalArgumentException("filename cannot be null"); + } + waitForReady(); warnOnNotMounted(); @@ -1569,164 +1553,98 @@ class MountService extends IMountService.Stub } public boolean isObbMounted(String filename) { + if (filename == null) { + throw new IllegalArgumentException("filename cannot be null"); + } + synchronized (mObbMounts) { - final ObbState obbState = mObbPathToStateMap.get(filename); - if (obbState != null) { - synchronized (obbState) { - return obbState.mounted; - } - } + return mObbPathToStateMap.containsKey(filename); } - return false; } - public void mountObb(String filename, String key, IObbActionListener token) + public void mountObb(String filename, String key, IObbActionListener token, int nonce) throws RemoteException { - waitForReady(); - warnOnNotMounted(); - if (filename == null) { throw new IllegalArgumentException("filename cannot be null"); - } else if (token == null) { - throw new IllegalArgumentException("token cannot be null"); } - final ObbState obbState; - - synchronized (mObbMounts) { - if (isObbMounted(filename)) { - try { - token.onObbResult(filename, Environment.MEDIA_MOUNTED); - } catch (RemoteException e) { - Slog.d(TAG, "Could not send unmount notification for: " + filename); - } - return; - } - - final int callerUid = Binder.getCallingUid(); - obbState = new ObbState(filename, token, callerUid); - addObbState(obbState); - } - - String hashedKey = null; - if (key != null) { - final MessageDigest md; - try { - md = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - Slog.e(TAG, "Could not load MD5 algorithm", e); - try { - token.onObbResult(filename, Environment.MEDIA_UNMOUNTED); - } catch (RemoteException e1) { - Slog.d(TAG, "Could not send unmount notification for: " + filename); - } - return; - } - - hashedKey = HexDump.toHexString(md.digest(key.getBytes())); + if (token == null) { + throw new IllegalArgumentException("token cannot be null"); } - ObbAction action = new MountObbAction(obbState, hashedKey); + final int callerUid = Binder.getCallingUid(); + final ObbState obbState = new ObbState(filename, callerUid, token, nonce); + final ObbAction action = new MountObbAction(obbState, key); mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); if (DEBUG_OBB) Slog.i(TAG, "Send to OBB handler: " + action.toString()); } - public void unmountObb(String filename, boolean force, IObbActionListener token) { + public void unmountObb(String filename, boolean force, IObbActionListener token, int nonce) + throws RemoteException { if (filename == null) { throw new IllegalArgumentException("filename cannot be null"); - } else if (token == null) { - throw new IllegalArgumentException("token cannot be null"); } - final ObbState obbState; - - synchronized (mObbMounts) { - if (!isObbMounted(filename)) { - try { - token.onObbResult(filename, Environment.MEDIA_UNMOUNTED); - } catch (RemoteException e) { - Slog.d(TAG, "Could not send unmount notification for: " + filename); - } - return; - } - - obbState = mObbPathToStateMap.get(filename); - - if (Binder.getCallingUid() != obbState.callerUid) { - throw new SecurityException("caller UID does not match original mount caller UID"); - } else if (!token.asBinder().equals(obbState.getBinder())) { - throw new SecurityException("caller does not match original mount caller"); - } - } - - ObbAction action = new UnmountObbAction(obbState, force); + final int callerUid = Binder.getCallingUid(); + final ObbState obbState = new ObbState(filename, callerUid, token, nonce); + final ObbAction action = new UnmountObbAction(obbState, force); mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); if (DEBUG_OBB) Slog.i(TAG, "Send to OBB handler: " + action.toString()); } - private void addObbState(ObbState obbState) throws RemoteException { - synchronized (mObbMounts) { - final IBinder binder = obbState.getBinder(); - List<ObbState> obbStates = mObbMounts.get(binder); - final boolean unique; - - if (obbStates == null) { - obbStates = new ArrayList<ObbState>(); - mObbMounts.put(binder, obbStates); - unique = true; - } else { - unique = obbStates.contains(obbState); - } - - if (unique) { - obbStates.add(obbState); - try { - obbState.link(); - } catch (RemoteException e) { - /* - * The binder died before we could link it, so clean up our - * state and return failure. - */ - obbStates.remove(obbState); - if (obbStates.isEmpty()) { - mObbMounts.remove(binder); - } + private void addObbStateLocked(ObbState obbState) throws RemoteException { + final IBinder binder = obbState.getBinder(); + List<ObbState> obbStates = mObbMounts.get(binder); - // Rethrow the error so mountObb can get it - throw e; + if (obbStates == null) { + obbStates = new ArrayList<ObbState>(); + mObbMounts.put(binder, obbStates); + } else { + for (final ObbState o : obbStates) { + if (o.filename.equals(obbState.filename)) { + throw new IllegalStateException("Attempt to add ObbState twice. " + + "This indicates an error in the MountService logic."); } } - - mObbPathToStateMap.put(obbState.filename, obbState); } - } - private void removeObbState(ObbState obbState) { - synchronized (mObbMounts) { - final IBinder binder = obbState.getBinder(); - final List<ObbState> obbStates = mObbMounts.get(binder); - if (obbStates != null) { - if (obbStates.remove(obbState)) { - obbState.unlink(); - } - if (obbStates.isEmpty()) { - mObbMounts.remove(binder); - } + obbStates.add(obbState); + try { + obbState.link(); + } catch (RemoteException e) { + /* + * The binder died before we could link it, so clean up our state + * and return failure. + */ + obbStates.remove(obbState); + if (obbStates.isEmpty()) { + mObbMounts.remove(binder); } - mObbPathToStateMap.remove(obbState.filename); + // Rethrow the error so mountObb can get it + throw e; } + + mObbPathToStateMap.put(obbState.filename, obbState); } - private void replaceObbState(ObbState oldObbState, ObbState newObbState) throws RemoteException { - synchronized (mObbMounts) { - removeObbState(oldObbState); - addObbState(newObbState); + private void removeObbStateLocked(ObbState obbState) { + final IBinder binder = obbState.getBinder(); + final List<ObbState> obbStates = mObbMounts.get(binder); + if (obbStates != null) { + if (obbStates.remove(obbState)) { + obbState.unlink(); + } + if (obbStates.isEmpty()) { + mObbMounts.remove(binder); + } } + + mObbPathToStateMap.remove(obbState.filename); } private class ObbActionHandler extends Handler { @@ -1825,6 +1743,47 @@ class MountService extends IMountService.Stub } break; } + case OBB_FLUSH_MOUNT_STATE: { + final String path = (String) msg.obj; + + if (DEBUG_OBB) + Slog.i(TAG, "Flushing all OBB state for path " + path); + + synchronized (mObbMounts) { + final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>(); + + final Iterator<Entry<String, ObbState>> i = + mObbPathToStateMap.entrySet().iterator(); + while (i.hasNext()) { + final Entry<String, ObbState> obbEntry = i.next(); + + /* + * If this entry's source file is in the volume path + * that got unmounted, remove it because it's no + * longer valid. + */ + if (obbEntry.getKey().startsWith(path)) { + obbStatesToRemove.add(obbEntry.getValue()); + } + } + + for (final ObbState obbState : obbStatesToRemove) { + if (DEBUG_OBB) + Slog.i(TAG, "Removing state for " + obbState.filename); + + removeObbStateLocked(obbState); + + try { + obbState.token.onObbResult(obbState.filename, obbState.nonce, + OnObbStateChangeListener.UNMOUNTED); + } catch (RemoteException e) { + Slog.i(TAG, "Couldn't send unmount notification for OBB: " + + obbState.filename); + } + } + } + break; + } } } @@ -1903,9 +1862,13 @@ class MountService extends IMountService.Stub return obbInfo; } - protected void sendNewStatusOrIgnore(String filename, String status) { + protected void sendNewStatusOrIgnore(int status) { + if (mObbState == null || mObbState.token == null) { + return; + } + try { - mObbState.token.onObbResult(filename, status); + mObbState.token.onObbResult(mObbState.filename, mObbState.nonce, status); } catch (RemoteException e) { Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged"); } @@ -1921,89 +1884,80 @@ class MountService extends IMountService.Stub } public void handleExecute() throws IOException, RemoteException { + waitForReady(); + warnOnNotMounted(); + final ObbInfo obbInfo = getObbInfo(); + if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) { + Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename + + " which is owned by " + obbInfo.packageName); + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED); + return; + } + + final boolean isMounted; + synchronized (mObbMounts) { + isMounted = mObbPathToStateMap.containsKey(obbInfo.filename); + } + if (isMounted) { + Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename); + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_ALREADY_MOUNTED); + return; + } + /* - * If someone tried to trick us with some weird characters, rectify - * it here. + * The filename passed in might not be the canonical name, so just + * set the filename to the canonicalized version. */ - if (!mObbState.filename.equals(obbInfo.filename)) { - if (DEBUG_OBB) - Slog.i(TAG, "OBB filename " + mObbState.filename + " is actually " - + obbInfo.filename); - - synchronized (mObbMounts) { - /* - * If the real filename is already mounted, discard this - * state and notify the caller that the OBB is already - * mounted. - */ - if (isObbMounted(obbInfo.filename)) { - if (DEBUG_OBB) - Slog.i(TAG, "OBB already mounted as " + obbInfo.filename); - - removeObbState(mObbState); - sendNewStatusOrIgnore(obbInfo.filename, Environment.MEDIA_MOUNTED); - return; - } + mObbState.filename = obbInfo.filename; - /* - * It's not already mounted, so we have to replace the state - * with the state containing the actual filename. - */ - ObbState newObbState = new ObbState(obbInfo.filename, mObbState.token, - mObbState.callerUid); - replaceObbState(mObbState, newObbState); - mObbState = newObbState; + final String hashedKey; + if (mKey == null) { + hashedKey = "none"; + } else { + final MessageDigest md; + try { + md = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + Slog.e(TAG, "Could not load MD5 algorithm", e); + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED); + return; } - } - if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) { - throw new IllegalArgumentException("Caller package does not match OBB file"); + hashedKey = HexDump.toHexString(md.digest(mKey.getBytes())); } - boolean mounted = false; - int rc; - synchronized (mObbState) { - if (mObbState.mounted) { - sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_MOUNTED); - return; + int rc = StorageResultCode.OperationSucceeded; + String cmd = String.format("obb mount %s %s %d", mObbState.filename, hashedKey, + mObbState.callerUid); + try { + mConnector.doCommand(cmd); + } catch (NativeDaemonConnectorException e) { + int code = e.getCode(); + if (code != VoldResponseCode.OpFailedStorageBusy) { + rc = StorageResultCode.OperationFailedInternalError; } + } - rc = StorageResultCode.OperationSucceeded; - String cmd = String.format("obb mount %s %s %d", mObbState.filename, - mKey != null ? mKey : "none", - mObbState.callerUid); - try { - mConnector.doCommand(cmd); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code != VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedInternalError; - } - } + if (rc == StorageResultCode.OperationSucceeded) { + if (DEBUG_OBB) + Slog.d(TAG, "Successfully mounted OBB " + mObbState.filename); - if (rc == StorageResultCode.OperationSucceeded) { - mObbState.mounted = mounted = true; + synchronized (mObbMounts) { + addObbStateLocked(mObbState); } - } - if (mounted) { - sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_MOUNTED); + sendNewStatusOrIgnore(OnObbStateChangeListener.MOUNTED); } else { Slog.e(TAG, "Couldn't mount OBB file: " + rc); - // We didn't succeed, so remove this from the mount-set. - removeObbState(mObbState); - - sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_UNMOUNTED); + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT); } } public void handleError() { - removeObbState(mObbState); - - sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_BAD_REMOVAL); + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL); } @Override @@ -2016,6 +1970,8 @@ class MountService extends IMountService.Stub sb.append(mObbState.callerUid); sb.append(",token="); sb.append(mObbState.token != null ? mObbState.token.toString() : "NULL"); + sb.append(",binder="); + sb.append(mObbState.token != null ? mObbState.getBinder().toString() : "null"); sb.append('}'); return sb.toString(); } @@ -2030,68 +1986,61 @@ class MountService extends IMountService.Stub } public void handleExecute() throws IOException { + waitForReady(); + warnOnNotMounted(); + final ObbInfo obbInfo = getObbInfo(); - /* - * If someone tried to trick us with some weird characters, rectify - * it here. - */ + final ObbState obbState; synchronized (mObbMounts) { - if (!isObbMounted(obbInfo.filename)) { - removeObbState(mObbState); - sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_UNMOUNTED); - return; - } + obbState = mObbPathToStateMap.get(obbInfo.filename); + } - if (!mObbState.filename.equals(obbInfo.filename)) { - removeObbState(mObbState); - mObbState = mObbPathToStateMap.get(obbInfo.filename); - } + if (obbState == null) { + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED); + return; } - boolean unmounted = false; - synchronized (mObbState) { - if (!mObbState.mounted) { - sendNewStatusOrIgnore(obbInfo.filename, Environment.MEDIA_UNMOUNTED); - return; - } + if (obbState.callerUid != mObbState.callerUid) { + Slog.w(TAG, "Permission denied attempting to unmount OBB " + obbInfo.filename + + " (owned by " + obbInfo.packageName + ")"); + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED); + return; + } - int rc = StorageResultCode.OperationSucceeded; - String cmd = String.format("obb unmount %s%s", mObbState.filename, - (mForceUnmount ? " force" : "")); - try { - mConnector.doCommand(cmd); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code == VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedStorageBusy; - } else if (code == VoldResponseCode.OpFailedStorageNotFound) { - // If it's not mounted then we've already won. - rc = StorageResultCode.OperationSucceeded; - } else { - rc = StorageResultCode.OperationFailedInternalError; - } - } + mObbState.filename = obbInfo.filename; - if (rc == StorageResultCode.OperationSucceeded) { - mObbState.mounted = false; - unmounted = true; + int rc = StorageResultCode.OperationSucceeded; + String cmd = String.format("obb unmount %s%s", mObbState.filename, + (mForceUnmount ? " force" : "")); + try { + mConnector.doCommand(cmd); + } catch (NativeDaemonConnectorException e) { + int code = e.getCode(); + if (code == VoldResponseCode.OpFailedStorageBusy) { + rc = StorageResultCode.OperationFailedStorageBusy; + } else if (code == VoldResponseCode.OpFailedStorageNotFound) { + // If it's not mounted then we've already won. + rc = StorageResultCode.OperationSucceeded; + } else { + rc = StorageResultCode.OperationFailedInternalError; } } - if (unmounted) { - removeObbState(mObbState); + if (rc == StorageResultCode.OperationSucceeded) { + synchronized (mObbMounts) { + removeObbStateLocked(obbState); + } - sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_UNMOUNTED); + sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED); } else { - sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_MOUNTED); + Slog.w(TAG, "Could not mount OBB: " + mObbState.filename); + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT); } } public void handleError() { - removeObbState(mObbState); - - sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_BAD_REMOVAL); + sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL); } @Override @@ -2107,7 +2056,7 @@ class MountService extends IMountService.Stub sb.append(",token="); sb.append(mObbState.token != null ? mObbState.token.toString() : "null"); sb.append(",binder="); - sb.append(mObbState.getBinder().toString()); + sb.append(mObbState.token != null ? mObbState.getBinder().toString() : "null"); sb.append('}'); return sb.toString(); } @@ -2122,16 +2071,27 @@ class MountService extends IMountService.Stub return; } - pw.println(" mObbMounts:"); - synchronized (mObbMounts) { - final Collection<List<ObbState>> obbStateLists = mObbMounts.values(); + pw.println(" mObbMounts:"); - for (final List<ObbState> obbStates : obbStateLists) { + final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet().iterator(); + while (binders.hasNext()) { + Entry<IBinder, List<ObbState>> e = binders.next(); + pw.print(" Key="); pw.println(e.getKey().toString()); + final List<ObbState> obbStates = e.getValue(); for (final ObbState obbState : obbStates) { - pw.print(" "); pw.println(obbState.toString()); + pw.print(" "); pw.println(obbState.toString()); } } + + pw.println(""); + pw.println(" mObbPathToStateMap:"); + final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator(); + while (maps.hasNext()) { + final Entry<String, ObbState> e = maps.next(); + pw.print(" "); pw.print(e.getKey()); + pw.print(" -> "); pw.println(e.getValue().toString()); + } } } } diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 5afabbd..15eaa9e 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -741,10 +741,6 @@ public class NotificationManagerService extends INotificationManager.Stub throw new IllegalArgumentException("contentView required: pkg=" + pkg + " id=" + id + " notification=" + notification); } - if (notification.contentIntent == null) { - throw new IllegalArgumentException("contentIntent required: pkg=" + pkg - + " id=" + id + " notification=" + notification); - } } synchronized (mNotificationList) { diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index a3d5961..608ffe1 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -7208,6 +7208,8 @@ class PackageManagerService extends IPackageManager.Stub { pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags)); pw.print(" installStatus="); pw.print(ps.installStatus); pw.print(" enabled="); pw.println(ps.enabled); + pw.print(" versionCode="); pw.print(ps.versionCode); + pw.print(" versionName="); pw.println(ps.pkg.mVersionName); if (ps.disabledComponents.size() > 0) { pw.println(" disabledComponents:"); for (String s : ps.disabledComponents) { diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 9d9ad26..36298d1 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -141,9 +141,7 @@ class PowerManagerService extends IPowerManager.Stub // used for noChangeLights in setPowerState() private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT; - static final boolean ANIMATE_SCREEN_LIGHTS = true; - static final boolean ANIMATE_BUTTON_LIGHTS = false; - static final boolean ANIMATE_KEYBOARD_LIGHTS = false; + boolean mAnimateScreenLights = true; static final int ANIM_STEPS = 60/4; // Slower animation for autobrightness changes @@ -201,15 +199,12 @@ class PowerManagerService extends IPowerManager.Stub private UnsynchronizedWakeLock mPreventScreenOnPartialLock; private UnsynchronizedWakeLock mProximityPartialLock; private HandlerThread mHandlerThread; + private HandlerThread mScreenOffThread; + private Handler mScreenOffHandler; private Handler mHandler; private final TimeoutTask mTimeoutTask = new TimeoutTask(); - private final LightAnimator mLightAnimator = new LightAnimator(); private final BrightnessState mScreenBrightness = new BrightnessState(SCREEN_BRIGHT_BIT); - private final BrightnessState mKeyboardBrightness - = new BrightnessState(KEYBOARD_BRIGHT_BIT); - private final BrightnessState mButtonBrightness - = new BrightnessState(BUTTON_BRIGHT_BIT); private boolean mStillNeedSleepNotification; private boolean mIsPowered = false; private IActivityManager mActivityService; @@ -261,6 +256,7 @@ class PowerManagerService extends IPowerManager.Stub private native void nativeInit(); private native void nativeSetPowerState(boolean screenOn, boolean screenBright); + private native void nativeStartSurfaceFlingerAnimation(); /* static PrintStream mLog; @@ -485,6 +481,35 @@ class PowerManagerService extends IPowerManager.Stub mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD); mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION); + nativeInit(); + synchronized (mLocks) { + updateNativePowerStateLocked(); + } + + mInitComplete = false; + mScreenOffThread = new HandlerThread("PowerManagerService.mScreenOffThread") { + @Override + protected void onLooperPrepared() { + mScreenOffHandler = new Handler(); + synchronized (mScreenOffThread) { + mInitComplete = true; + mScreenOffThread.notifyAll(); + } + } + }; + mScreenOffThread.start(); + + synchronized (mScreenOffThread) { + while (!mInitComplete) { + try { + mScreenOffThread.wait(); + } catch (InterruptedException e) { + // Ignore + } + } + } + + mInitComplete = false; mHandlerThread = new HandlerThread("PowerManagerService") { @Override protected void onLooperPrepared() { @@ -531,6 +556,9 @@ class PowerManagerService extends IPowerManager.Stub Resources resources = mContext.getResources(); + mAnimateScreenLights = resources.getBoolean( + com.android.internal.R.bool.config_animateScreenLights); + mUnplugTurnsOnScreen = resources.getBoolean( com.android.internal.R.bool.config_unplugTurnsOnScreen); @@ -1093,8 +1121,6 @@ class PowerManagerService extends IPowerManager.Stub pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness); pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled); mScreenBrightness.dump(pw, " mScreenBrightness: "); - mKeyboardBrightness.dump(pw, " mKeyboardBrightness: "); - mButtonBrightness.dump(pw, " mButtonBrightness: "); int N = mLocks.size(); pw.println(); @@ -1724,7 +1750,8 @@ class PowerManagerService extends IPowerManager.Stub // I don't think we need to check the current state here because all of these // Power.setScreenState and sendNotificationLocked can both handle being // called multiple times in the same state. -joeo - EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, mTouchCycles); + EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, + mTouchCycles); mLastTouchDown = 0; int err = setScreenStateLocked(false); if (err == 0) { @@ -1754,145 +1781,95 @@ class PowerManagerService extends IPowerManager.Stub int onMask = 0; int preferredBrightness = getPreferredBrightness(); - boolean startAnimation = false; if ((difference & KEYBOARD_BRIGHT_BIT) != 0) { - if (ANIMATE_KEYBOARD_LIGHTS) { - if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { - mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, - ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS, - Power.BRIGHTNESS_ON); - } else { - mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_ON, - ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS, - Power.BRIGHTNESS_OFF); - } - startAnimation = true; + if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { + offMask |= KEYBOARD_BRIGHT_BIT; } else { - if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { - offMask |= KEYBOARD_BRIGHT_BIT; - } else { - onMask |= KEYBOARD_BRIGHT_BIT; - } + onMask |= KEYBOARD_BRIGHT_BIT; } } if ((difference & BUTTON_BRIGHT_BIT) != 0) { - if (ANIMATE_BUTTON_LIGHTS) { - if ((newState & BUTTON_BRIGHT_BIT) == 0) { - mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, - ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, - Power.BRIGHTNESS_ON); - } else { - mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_ON, - ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, - Power.BRIGHTNESS_OFF); - } - startAnimation = true; + if ((newState & BUTTON_BRIGHT_BIT) == 0) { + offMask |= BUTTON_BRIGHT_BIT; } else { - if ((newState & BUTTON_BRIGHT_BIT) == 0) { - offMask |= BUTTON_BRIGHT_BIT; - } else { - onMask |= BUTTON_BRIGHT_BIT; - } + onMask |= BUTTON_BRIGHT_BIT; } } if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { - if (ANIMATE_SCREEN_LIGHTS) { - int nominalCurrentValue = -1; - // If there was an actual difference in the light state, then - // figure out the "ideal" current value based on the previous - // state. Otherwise, this is a change due to the brightness - // override, so we want to animate from whatever the current - // value is. - if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { - switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) { - case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT: - nominalCurrentValue = preferredBrightness; - break; - case SCREEN_ON_BIT: - nominalCurrentValue = Power.BRIGHTNESS_DIM; - break; - case 0: - nominalCurrentValue = Power.BRIGHTNESS_OFF; - break; - case SCREEN_BRIGHT_BIT: - default: - // not possible - nominalCurrentValue = (int)mScreenBrightness.curValue; - break; - } + int nominalCurrentValue = -1; + // If there was an actual difference in the light state, then + // figure out the "ideal" current value based on the previous + // state. Otherwise, this is a change due to the brightness + // override, so we want to animate from whatever the current + // value is. + if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { + switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) { + case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT: + nominalCurrentValue = preferredBrightness; + break; + case SCREEN_ON_BIT: + nominalCurrentValue = Power.BRIGHTNESS_DIM; + break; + case 0: + nominalCurrentValue = Power.BRIGHTNESS_OFF; + break; + case SCREEN_BRIGHT_BIT: + default: + // not possible + nominalCurrentValue = (int)mScreenBrightness.curValue; + break; } - int brightness = preferredBrightness; - int steps = ANIM_STEPS; - if ((newState & SCREEN_BRIGHT_BIT) == 0) { - // dim or turn off backlight, depending on if the screen is on - // the scale is because the brightness ramp isn't linear and this biases - // it so the later parts take longer. - final float scale = 1.5f; - float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness); - if (ratio > 1.0f) ratio = 1.0f; - if ((newState & SCREEN_ON_BIT) == 0) { - if ((oldState & SCREEN_BRIGHT_BIT) != 0) { - // was bright - steps = ANIM_STEPS; - } else { - // was dim - steps = (int)(ANIM_STEPS*ratio*scale); - } - brightness = Power.BRIGHTNESS_OFF; + } + int brightness = preferredBrightness; + int steps = ANIM_STEPS; + if ((newState & SCREEN_BRIGHT_BIT) == 0) { + // dim or turn off backlight, depending on if the screen is on + // the scale is because the brightness ramp isn't linear and this biases + // it so the later parts take longer. + final float scale = 1.5f; + float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness); + if (ratio > 1.0f) ratio = 1.0f; + if ((newState & SCREEN_ON_BIT) == 0) { + if ((oldState & SCREEN_BRIGHT_BIT) != 0) { + // was bright + steps = ANIM_STEPS; } else { - if ((oldState & SCREEN_ON_BIT) != 0) { - // was bright - steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale); - } else { - // was dim - steps = (int)(ANIM_STEPS*ratio); - } - if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) { - // If the "stay on while plugged in" option is - // turned on, then the screen will often not - // automatically turn off while plugged in. To - // still have a sense of when it is inactive, we - // will then count going dim as turning off. - mScreenOffTime = SystemClock.elapsedRealtime(); - } - brightness = Power.BRIGHTNESS_DIM; + // was dim + steps = (int)(ANIM_STEPS*ratio*scale); } - } - long identity = Binder.clearCallingIdentity(); - try { - mBatteryStats.noteScreenBrightness(brightness); - } catch (RemoteException e) { - // Nothing interesting to do. - } finally { - Binder.restoreCallingIdentity(identity); - } - if (mScreenBrightness.setTargetLocked(brightness, - steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) { - startAnimation = true; - } - } else { - if ((newState & SCREEN_BRIGHT_BIT) == 0) { - // dim or turn off backlight, depending on if the screen is on - if ((newState & SCREEN_ON_BIT) == 0) { - offMask |= SCREEN_BRIGHT_BIT; + brightness = Power.BRIGHTNESS_OFF; + } else { + if ((oldState & SCREEN_ON_BIT) != 0) { + // was bright + steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale); } else { - dimMask |= SCREEN_BRIGHT_BIT; + // was dim + steps = (int)(ANIM_STEPS*ratio); } - } else { - onMask |= SCREEN_BRIGHT_BIT; + if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) { + // If the "stay on while plugged in" option is + // turned on, then the screen will often not + // automatically turn off while plugged in. To + // still have a sense of when it is inactive, we + // will then count going dim as turning off. + mScreenOffTime = SystemClock.elapsedRealtime(); + } + brightness = Power.BRIGHTNESS_DIM; } } - } - - if (startAnimation) { - if (mSpew) { - Slog.i(TAG, "Scheduling light animator!"); + long identity = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteScreenBrightness(brightness); + } catch (RemoteException e) { + // Nothing interesting to do. + } finally { + Binder.restoreCallingIdentity(identity); } - mHandler.removeCallbacks(mLightAnimator); - mHandler.post(mLightAnimator); + mScreenBrightness.setTargetLocked(brightness, steps, + INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); } if (offMask != 0) { @@ -1934,7 +1911,7 @@ class PowerManagerService extends IPowerManager.Stub } } - class BrightnessState { + class BrightnessState implements Runnable { final int mask; boolean initialized; @@ -1954,13 +1931,13 @@ class PowerManagerService extends IPowerManager.Stub + " delta=" + delta); } - boolean setTargetLocked(int target, int stepsToTarget, int initialValue, + void setTargetLocked(int target, int stepsToTarget, int initialValue, int nominalCurrentValue) { if (!initialized) { initialized = true; curValue = (float)initialValue; } else if (targetValue == target) { - return false; + return; } targetValue = target; delta = (targetValue - @@ -1974,7 +1951,12 @@ class PowerManagerService extends IPowerManager.Stub + noticeMe); } animating = true; - return true; + + if (mSpew) { + Slog.i(TAG, "scheduling light animator"); + } + mScreenOffHandler.removeCallbacks(this); + mScreenOffHandler.post(this); } boolean stepLocked() { @@ -2000,32 +1982,50 @@ class PowerManagerService extends IPowerManager.Stub more = false; } } - //Slog.i(TAG, "Animating brightess " + curIntValue + ": " + mask); + if (mSpew) Slog.d(TAG, "Animating curIntValue=" + curIntValue + ": " + mask); setLightBrightness(mask, curIntValue); + finishAnimation(more, curIntValue); + return more; + } + + void jumpToTarget() { + if (mSpew) Slog.d(TAG, "jumpToTarget targetValue=" + targetValue + ": " + mask); + setLightBrightness(mask, targetValue); + final int tv = targetValue; + curValue = tv; + targetValue = -1; + finishAnimation(false, tv); + } + + private void finishAnimation(boolean more, int curIntValue) { animating = more; if (!more) { if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) { screenOffFinishedAnimatingLocked(mScreenOffReason); } } - return more; } - } - private class LightAnimator implements Runnable { public void run() { - synchronized (mLocks) { - long now = SystemClock.uptimeMillis(); - boolean more = mScreenBrightness.stepLocked(); - if (mKeyboardBrightness.stepLocked()) { - more = true; + if (mAnimateScreenLights) { + synchronized (mLocks) { + long now = SystemClock.uptimeMillis(); + boolean more = mScreenBrightness.stepLocked(); + if (more) { + mScreenOffHandler.postAtTime(this, now+(1000/60)); + } } - if (mButtonBrightness.stepLocked()) { - more = true; + } else { + boolean animate; + boolean jump; + synchronized (mLocks) { + jump = animating; // we haven't already run this animation + animate = jump && targetValue == Power.BRIGHTNESS_OFF; // we're turning off } - if (more) { - mHandler.postAtTime(mLightAnimator, now+(1000/60)); + if (animate) { + nativeStartSurfaceFlingerAnimation(); } + mScreenBrightness.jumpToTarget(); } } } @@ -2343,49 +2343,15 @@ class PowerManagerService extends IPowerManager.Stub Slog.d(TAG, "keyboardValue " + keyboardValue); } - boolean startAnimation = false; if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) { - if (ANIMATE_SCREEN_LIGHTS) { - if (mScreenBrightness.setTargetLocked(lcdValue, - AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS, - (int)mScreenBrightness.curValue)) { - startAnimation = true; - } - } else { - int brightnessMode = (mAutoBrightessEnabled - ? LightsService.BRIGHTNESS_MODE_SENSOR - : LightsService.BRIGHTNESS_MODE_USER); - mLcdLight.setBrightness(lcdValue, brightnessMode); - } + mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS, + INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue); } if (mButtonBrightnessOverride < 0) { - if (ANIMATE_BUTTON_LIGHTS) { - if (mButtonBrightness.setTargetLocked(buttonValue, - AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, - (int)mButtonBrightness.curValue)) { - startAnimation = true; - } - } else { - mButtonLight.setBrightness(buttonValue); - } + mButtonLight.setBrightness(buttonValue); } if (mButtonBrightnessOverride < 0 || !mKeyboardVisible) { - if (ANIMATE_KEYBOARD_LIGHTS) { - if (mKeyboardBrightness.setTargetLocked(keyboardValue, - AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, - (int)mKeyboardBrightness.curValue)) { - startAnimation = true; - } - } else { - mKeyboardLight.setBrightness(keyboardValue); - } - } - if (startAnimation) { - if (mDebugLightSensor) { - Slog.i(TAG, "lightSensorChangedLocked scheduling light animator"); - } - mHandler.removeCallbacks(mLightAnimator); - mHandler.post(mLightAnimator); + mKeyboardLight.setBrightness(keyboardValue); } } } @@ -2754,6 +2720,7 @@ class PowerManagerService extends IPowerManager.Stub } } + // for watchdog public void monitor() { synchronized (mLocks) { } } @@ -2773,34 +2740,23 @@ class PowerManagerService extends IPowerManager.Stub public void setBacklightBrightness(int brightness) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); // Don't let applications turn the screen all the way off - brightness = Math.max(brightness, Power.BRIGHTNESS_DIM); - mLcdLight.setBrightness(brightness); - mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0); - mButtonLight.setBrightness(brightness); - long identity = Binder.clearCallingIdentity(); - try { - mBatteryStats.noteScreenBrightness(brightness); - } catch (RemoteException e) { - Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e); - } finally { - Binder.restoreCallingIdentity(identity); - } + synchronized (mLocks) { + brightness = Math.max(brightness, Power.BRIGHTNESS_DIM); + mLcdLight.setBrightness(brightness); + mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0); + mButtonLight.setBrightness(brightness); + long identity = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteScreenBrightness(brightness); + } catch (RemoteException e) { + Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e); + } finally { + Binder.restoreCallingIdentity(identity); + } - // update our animation state - if (ANIMATE_SCREEN_LIGHTS) { - mScreenBrightness.curValue = brightness; - mScreenBrightness.animating = false; - mScreenBrightness.targetValue = -1; - } - if (ANIMATE_KEYBOARD_LIGHTS) { - mKeyboardBrightness.curValue = brightness; - mKeyboardBrightness.animating = false; - mKeyboardBrightness.targetValue = -1; - } - if (ANIMATE_BUTTON_LIGHTS) { - mButtonBrightness.curValue = brightness; - mButtonBrightness.animating = false; - mButtonBrightness.targetValue = -1; + // update our animation state + mScreenBrightness.targetValue = brightness; + mScreenBrightness.jumpToTarget(); } } diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java index b1baec5..66e0214 100644 --- a/services/java/com/android/server/StatusBarManagerService.java +++ b/services/java/com/android/server/StatusBarManagerService.java @@ -72,6 +72,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub // We usually call it lights out mode, but double negatives are annoying boolean mLightsOn = true; + boolean mMenuVisible = false; + private class DisableRecord implements IBinder.DeathRecipient { String pkg; int what; @@ -246,6 +248,32 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + /** + * Hide or show the on-screen Menu key. Only call this from the window manager, typically in + * response to a window with FLAG_NEEDS_MENU_KEY set. + */ + public void setMenuKeyVisible(final boolean visible) { + enforceStatusBar(); + + if (SPEW) Slog.d(TAG, (visible?"showing":"hiding") + " MENU key"); + + synchronized(mLock) { + if (mMenuVisible != visible) { + mMenuVisible = visible; + mHandler.post(new Runnable() { + public void run() { + if (mBar != null) { + try { + mBar.setMenuKeyVisible(visible); + } catch (RemoteException ex) { + } + } + } + }); + } + } + } + /** * This is used for the automatic version of lights-out mode. Only call this from * the window manager. @@ -317,7 +345,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub // ================================================================================ public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList, List<IBinder> notificationKeys, List<StatusBarNotification> notifications, - boolean lightsOn[]) { + boolean switches[]) { enforceStatusBarService(); Slog.i(TAG, "registerStatusBar bar=" + bar); @@ -332,7 +360,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } synchronized (mLock) { - lightsOn[0] = mLightsOn; + switches[0] = mLightsOn; + switches[1] = mMenuVisible; } } diff --git a/services/jni/Android.mk b/services/jni/Android.mk index 459551d..d10f54f 100644 --- a/services/jni/Android.mk +++ b/services/jni/Android.mk @@ -24,7 +24,8 @@ LOCAL_SHARED_LIBRARIES := \ libnativehelper \ libsystem_server \ libutils \ - libui + libui \ + libsurfaceflinger_client LOCAL_STATIC_LIBRARIES := libusbhost diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index e15e8d8..599163b 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -842,31 +842,35 @@ void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; } - const int32_t WM_ACTION_PASS_TO_USER = 1; - const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2; - const int32_t WM_ACTION_GO_TO_SLEEP = 4; + // Policy: + // - Ignore untrusted events and pass them along. + // - Ask the window manager what to do with normal events and trusted injected events. + // - For normal events wake and brighten the screen if currently off or dim. + if ((policyFlags & POLICY_FLAG_TRUSTED)) { + const int32_t WM_ACTION_PASS_TO_USER = 1; + const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2; + const int32_t WM_ACTION_GO_TO_SLEEP = 4; + + bool isScreenOn = this->isScreenOn(); + bool isScreenBright = this->isScreenBright(); - bool isScreenOn = this->isScreenOn(); - bool isScreenBright = this->isScreenBright(); - - JNIEnv* env = jniEnv(); - jint wmActions = env->CallIntMethod(mCallbacksObj, - gCallbacksClassInfo.interceptKeyBeforeQueueing, - when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn); - if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { - wmActions = 0; - } - - if (policyFlags & POLICY_FLAG_TRUSTED) { - if (! isScreenOn) { - // Key presses and releases wake the device. - policyFlags |= POLICY_FLAG_WOKE_HERE; - flags |= AKEY_EVENT_FLAG_WOKE_HERE; + JNIEnv* env = jniEnv(); + jint wmActions = env->CallIntMethod(mCallbacksObj, + gCallbacksClassInfo.interceptKeyBeforeQueueing, + when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn); + if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { + wmActions = 0; } - if (! isScreenBright) { - // Key presses and releases brighten the screen if dimmed. - policyFlags |= POLICY_FLAG_BRIGHT_HERE; + if (!(flags & POLICY_FLAG_INJECTED)) { + if (!isScreenOn) { + policyFlags |= POLICY_FLAG_WOKE_HERE; + flags |= AKEY_EVENT_FLAG_WOKE_HERE; + } + + if (!isScreenBright) { + policyFlags |= POLICY_FLAG_BRIGHT_HERE; + } } if (wmActions & WM_ACTION_GO_TO_SLEEP) { @@ -876,9 +880,11 @@ void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) { android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT); } - } - if (wmActions & WM_ACTION_PASS_TO_USER) { + if (wmActions & WM_ACTION_PASS_TO_USER) { + policyFlags |= POLICY_FLAG_PASS_TO_USER; + } + } else { policyFlags |= POLICY_FLAG_PASS_TO_USER; } } @@ -888,33 +894,47 @@ void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags); #endif - if (isScreenOn()) { - // Only dispatch events when the device is awake. - // Do not wake the device. - policyFlags |= POLICY_FLAG_PASS_TO_USER; - - if ((policyFlags & POLICY_FLAG_TRUSTED) && !isScreenBright()) { - // Brighten the screen if dimmed. - policyFlags |= POLICY_FLAG_BRIGHT_HERE; + // Policy: + // - Ignore untrusted events and pass them along. + // - No special filtering for injected events required at this time. + // - Filter normal events based on screen state. + // - For normal events brighten (but do not wake) the screen if currently dim. + if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) { + if (isScreenOn()) { + policyFlags |= POLICY_FLAG_PASS_TO_USER; + + if (!isScreenBright()) { + policyFlags |= POLICY_FLAG_BRIGHT_HERE; + } } + } else { + policyFlags |= POLICY_FLAG_PASS_TO_USER; } } bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel, const KeyEvent* keyEvent, uint32_t policyFlags) { - JNIEnv* env = jniEnv(); + // Policy: + // - Ignore untrusted events and pass them along. + // - Filter normal events and trusted injected events through the window manager policy to + // handle the HOME key and the like. + if (policyFlags & POLICY_FLAG_TRUSTED) { + JNIEnv* env = jniEnv(); + + // Note: inputChannel may be null. + jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel); + jboolean consumed = env->CallBooleanMethod(mCallbacksObj, + gCallbacksClassInfo.interceptKeyBeforeDispatching, + inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(), + keyEvent->getKeyCode(), keyEvent->getMetaState(), + keyEvent->getRepeatCount(), policyFlags); + bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); - // Note: inputChannel may be null. - jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel); - jboolean consumed = env->CallBooleanMethod(mCallbacksObj, - gCallbacksClassInfo.interceptKeyBeforeDispatching, - inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(), - keyEvent->getKeyCode(), keyEvent->getMetaState(), - keyEvent->getRepeatCount(), policyFlags); - bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); - - env->DeleteLocalRef(inputChannelObj); - return consumed && ! error; + env->DeleteLocalRef(inputChannelObj); + return consumed && ! error; + } else { + return false; + } } void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) { diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp index 146c177..2ec20bd 100644 --- a/services/jni/com_android_server_PowerManagerService.cpp +++ b/services/jni/com_android_server_PowerManagerService.cpp @@ -20,9 +20,14 @@ #include "JNIHelp.h" #include "jni.h" + #include <limits.h> + #include <android_runtime/AndroidRuntime.h> #include <utils/Timers.h> +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/SurfaceComposerClient.h> + #include "com_android_server_PowerManagerService.h" namespace android { @@ -119,6 +124,12 @@ static void android_server_PowerManagerService_nativeSetPowerState(JNIEnv* env, gScreenBright = screenBright; } +static void android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation(JNIEnv* env, + jobject obj) { + sp<ISurfaceComposer> s(ComposerService::getComposerService()); + s->turnElectronBeamOff(0); +} + // ---------------------------------------------------------------------------- static JNINativeMethod gPowerManagerServiceMethods[] = { @@ -127,6 +138,8 @@ static JNINativeMethod gPowerManagerServiceMethods[] = { (void*) android_server_PowerManagerService_nativeInit }, { "nativeSetPowerState", "(ZZ)V", (void*) android_server_PowerManagerService_nativeSetPowerState }, + { "nativeStartSurfaceFlingerAnimation", "()V", + (void*) android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation }, }; #define FIND_CLASS(var, className) \ diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp index 1d09f84..fe9a5ab 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp @@ -359,7 +359,7 @@ status_t DisplayHardwareBase::ConsoleManagerThread::initCheck() const DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger, uint32_t displayIndex) - : mCanDraw(true) + : mCanDraw(true), mScreenAcquired(true) { mDisplayEventThread = new DisplayEventThread(flinger); if (mDisplayEventThread->initCheck() != NO_ERROR) { @@ -374,18 +374,21 @@ DisplayHardwareBase::~DisplayHardwareBase() mDisplayEventThread->requestExitAndWait(); } +void DisplayHardwareBase::setCanDraw(bool canDraw) +{ + mCanDraw = canDraw; +} bool DisplayHardwareBase::canDraw() const { - return mCanDraw; + return mCanDraw && mScreenAcquired; } void DisplayHardwareBase::releaseScreen() const { status_t err = mDisplayEventThread->releaseScreen(); if (err >= 0) { - //LOGD("screen given-up"); - mCanDraw = false; + mScreenAcquired = false; } } @@ -393,9 +396,14 @@ void DisplayHardwareBase::acquireScreen() const { status_t err = mDisplayEventThread->acquireScreen(); if (err >= 0) { - //LOGD("screen returned"); mCanDraw = true; + mScreenAcquired = true; } } +bool DisplayHardwareBase::isScreenAcquired() const +{ + return mScreenAcquired; +} + }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h index 8369bb8..fa6a0c4 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h @@ -40,7 +40,11 @@ public: // console managment void releaseScreen() const; void acquireScreen() const; + bool isScreenAcquired() const; + bool canDraw() const; + void setCanDraw(bool canDraw); + private: class DisplayEventThreadBase : public Thread { @@ -89,6 +93,7 @@ private: sp<DisplayEventThreadBase> mDisplayEventThread; mutable int mCanDraw; + mutable int mScreenAcquired; }; }; // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e6bdfd1..97365aa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -430,14 +430,14 @@ void SurfaceFlinger::handleConsoleEvents() hw.acquireScreen(); } - if (mDeferReleaseConsole && hw.canDraw()) { + if (mDeferReleaseConsole && hw.isScreenAcquired()) { // We got the release signal before the acquire signal mDeferReleaseConsole = false; hw.releaseScreen(); } if (what & eConsoleReleased) { - if (hw.canDraw()) { + if (hw.isScreenAcquired()) { hw.releaseScreen(); } else { mDeferReleaseConsole = true; @@ -1558,6 +1558,7 @@ status_t SurfaceFlinger::onTransact( case FREEZE_DISPLAY: case UNFREEZE_DISPLAY: case BOOT_FINISHED: + case TURN_ELECTRON_BEAM_OFF: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); @@ -1651,6 +1652,231 @@ status_t SurfaceFlinger::onTransact( return err; } + +// --------------------------------------------------------------------------- + +status_t SurfaceFlinger::turnElectronBeamOffImplLocked() +{ + status_t result = PERMISSION_DENIED; + + if (!GLExtensions::getInstance().haveFramebufferObject()) + return INVALID_OPERATION; + + // get screen geometry + const int dpy = 0; + const DisplayHardware& hw(graphicPlane(dpy).displayHardware()); + if (!hw.canDraw()) { + // we're already off + return NO_ERROR; + } + + const uint32_t hw_w = hw.getWidth(); + const uint32_t hw_h = hw.getHeight(); + const Region screenBounds(hw.bounds()); + GLfloat u = 1; + GLfloat v = 1; + + // make sure to clear all GL error flags + while ( glGetError() != GL_NO_ERROR ) ; + + // create a FBO + GLuint name, tname; + glGenTextures(1, &tname); + glBindTexture(GL_TEXTURE_2D, tname); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + if (glGetError() != GL_NO_ERROR) { + GLint tw = (2 << (31 - clz(hw_w))); + GLint th = (2 << (31 - clz(hw_h))); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + u = GLfloat(hw_w) / tw; + v = GLfloat(hw_h) / th; + } + glGenFramebuffersOES(1, &name); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); + glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); + + GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); + if (status == GL_FRAMEBUFFER_COMPLETE_OES) { + // redraw the screen entirely... + glClearColor(0,0,0,1); + glClear(GL_COLOR_BUFFER_BIT); + const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); + const size_t count = layers.size(); + for (size_t i=0 ; i<count ; ++i) { + const sp<LayerBase>& layer(layers[i]); + layer->drawForSreenShot(); + } + // back to main framebuffer + glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); + glDisable(GL_SCISSOR_TEST); + + GLfloat vtx[8]; + const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} }; + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tname); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, vtx); + + class s_curve_interpolator { + const float nbFrames, s, v; + public: + s_curve_interpolator(int nbFrames, float s) + : nbFrames(1.0f / (nbFrames-1)), s(s), + v(1.0f + expf(-s + 0.5f*s)) { + } + float operator()(int f) { + const float x = f * nbFrames; + return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f; + } + }; + + class v_stretch { + const GLfloat hw_w, hw_h; + public: + v_stretch(uint32_t hw_w, uint32_t hw_h) + : hw_w(hw_w), hw_h(hw_h) { + } + void operator()(GLfloat* vtx, float v) { + const GLfloat w = hw_w + (hw_w * v); + const GLfloat h = hw_h - (hw_h * v); + const GLfloat x = (hw_w - w) * 0.5f; + const GLfloat y = (hw_h - h) * 0.5f; + vtx[0] = x; vtx[1] = y; + vtx[2] = x; vtx[3] = y + h; + vtx[4] = x + w; vtx[5] = y + h; + vtx[6] = x + w; vtx[7] = y; + } + }; + + class h_stretch { + const GLfloat hw_w, hw_h; + public: + h_stretch(uint32_t hw_w, uint32_t hw_h) + : hw_w(hw_w), hw_h(hw_h) { + } + void operator()(GLfloat* vtx, float v) { + const GLfloat w = hw_w - (hw_w * v); + const GLfloat h = 1.0f; + const GLfloat x = (hw_w - w) * 0.5f; + const GLfloat y = (hw_h - h) * 0.5f; + vtx[0] = x; vtx[1] = y; + vtx[2] = x; vtx[3] = y + h; + vtx[4] = x + w; vtx[5] = y + h; + vtx[6] = x + w; vtx[7] = y; + } + }; + + // the full animation is 24 frames + const int nbFrames = 12; + + v_stretch vverts(hw_w, hw_h); + s_curve_interpolator itr(nbFrames, 7.5f); + s_curve_interpolator itg(nbFrames, 8.0f); + s_curve_interpolator itb(nbFrames, 8.5f); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + for (int i=0 ; i<nbFrames ; i++) { + float x, y, w, h; + const float vr = itr(i); + const float vg = itg(i); + const float vb = itb(i); + + // clear screen + glColorMask(1,1,1,1); + glClear(GL_COLOR_BUFFER_BIT); + glEnable(GL_TEXTURE_2D); + + // draw the red plane + vverts(vtx, vr); + glColorMask(1,0,0,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // draw the green plane + vverts(vtx, vg); + glColorMask(0,1,0,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // draw the blue plane + vverts(vtx, vb); + glColorMask(0,0,1,1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // draw the white highlight (we use the last vertices) + glDisable(GL_TEXTURE_2D); + glColorMask(1,1,1,1); + glColor4f(vg, vg, vg, 1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + hw.flip(screenBounds); + } + + h_stretch hverts(hw_w, hw_h); + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glColorMask(1,1,1,1); + for (int i=0 ; i<nbFrames ; i++) { + const float v = itg(i); + hverts(vtx, v); + glClear(GL_COLOR_BUFFER_BIT); + glColor4f(1-v, 1-v, 1-v, 1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + hw.flip(screenBounds); + } + + glColorMask(1,1,1,1); + glEnable(GL_SCISSOR_TEST); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + result = NO_ERROR; + } else { + // release FBO resources + glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); + result = BAD_VALUE; + } + + glDeleteFramebuffersOES(1, &name); + glDeleteTextures(1, &tname); + + if (result == NO_ERROR) { + DisplayHardware& hw(graphicPlane(dpy).editDisplayHardware()); + hw.setCanDraw(false); + } + + return result; +} + +status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode) +{ + if (!GLExtensions::getInstance().haveFramebufferObject()) + return INVALID_OPERATION; + + class MessageTurnElectronBeamOff : public MessageBase { + SurfaceFlinger* flinger; + status_t result; + public: + MessageTurnElectronBeamOff(SurfaceFlinger* flinger) + : flinger(flinger), result(PERMISSION_DENIED) { + } + status_t getResult() const { + return result; + } + virtual bool handler() { + Mutex::Autolock _l(flinger->mStateLock); + result = flinger->turnElectronBeamOffImplLocked(); + return true; + } + }; + + sp<MessageBase> msg = new MessageTurnElectronBeamOff(this); + status_t res = postMessageSync(msg); + if (res == NO_ERROR) { + res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult(); + } + return res; +} + // --------------------------------------------------------------------------- status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, @@ -2115,6 +2341,10 @@ const DisplayHardware& GraphicPlane::displayHardware() const { return *mHw; } +DisplayHardware& GraphicPlane::editDisplayHardware() { + return *mHw; +} + const Transform& GraphicPlane::transform() const { return mGlobalTransform; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 732e57e..3470d87 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -141,6 +141,7 @@ public: int getHeight() const; const DisplayHardware& displayHardware() const; + DisplayHardware& editDisplayHardware(); const Transform& transform() const; EGLDisplay getEGLDisplay() const; @@ -200,6 +201,7 @@ public: PixelFormat* format, uint32_t reqWidth, uint32_t reqHeight); + virtual status_t turnElectronBeamOff(int32_t mode); void screenReleased(DisplayID dpy); void screenAcquired(DisplayID dpy); @@ -326,6 +328,8 @@ private: uint32_t* width, uint32_t* height, PixelFormat* format, uint32_t reqWidth = 0, uint32_t reqHeight = 0); + status_t turnElectronBeamOffImplLocked(); + friend class FreezeLock; sp<FreezeLock> getFreezeLock() const; inline void incFreezeCount() { diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java index b09df82..3f0ec0a 100644 --- a/telephony/java/com/android/internal/telephony/CallManager.java +++ b/telephony/java/com/android/internal/telephony/CallManager.java @@ -56,7 +56,7 @@ public final class CallManager { private static final String LOG_TAG ="CallManager"; private static final boolean DBG = true; - private static final boolean VDBG = true; + private static final boolean VDBG = false; private static final int EVENT_DISCONNECT = 100; private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101; @@ -292,7 +292,7 @@ public final class CallManager { if (basePhone != null && !mPhones.contains(basePhone)) { - if (VDBG) { + if (DBG) { Log.d(LOG_TAG, "registerPhone(" + phone.getPhoneName() + " " + phone + ")"); } @@ -319,7 +319,7 @@ public final class CallManager { if (basePhone != null && mPhones.contains(basePhone)) { - if (VDBG) { + if (DBG) { Log.d(LOG_TAG, "unregisterPhone(" + phone.getPhoneName() + " " + phone + ")"); } @@ -487,7 +487,7 @@ public final class CallManager { boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle()); boolean sameChannel = (activePhone == ringingPhone); - if (DBG) { + if (VDBG) { Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel); } diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index c67b995..db16dec 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -390,8 +390,8 @@ public class CallerInfo { */ public String toString() { return new StringBuilder(384) - .append("\nname: " + name) - .append("\nphoneNumber: " + phoneNumber) + .append("\nname: " + /*name*/ "nnnnnn") + .append("\nphoneNumber: " + /*phoneNumber*/ "xxxxxxx") .append("\ncnapName: " + cnapName) .append("\nnumberPresentation: " + numberPresentation) .append("\nnamePresentation: " + namePresentation) @@ -402,8 +402,8 @@ public class CallerInfo { .append("\nphotoResource: " + photoResource) .append("\nperson_id: " + person_id) .append("\nneedUpdate: " + needUpdate) - .append("\ncontactRefUri: " + contactRefUri) - .append("\ncontactRingtoneUri: " + contactRefUri) + .append("\ncontactRefUri: " + /*contactRefUri*/ "xxxxxxx") + .append("\ncontactRingtoneUri: " + /*contactRefUri*/ "xxxxxxx") .append("\nshouldSendToVoicemail: " + shouldSendToVoicemail) .append("\ncachedPhoto: " + cachedPhoto) .append("\nisCachedPhotoCurrent: " + isCachedPhotoCurrent) diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index a967850..de5bb943 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -136,7 +136,7 @@ public class CallerInfoAsyncQuery { } else { if (DBG) log("Processing event: " + cw.event + " token (arg1): " + msg.arg1 + - " command: " + msg.what + " query URI: " + args.uri); + " command: " + msg.what + " query URI: " + sanitizeUriToString(args.uri)); switch (cw.event) { case EVENT_NEW_QUERY: @@ -302,7 +302,7 @@ public class CallerInfoAsyncQuery { OnQueryCompleteListener listener, Object cookie) { if (DBG) { log("##### CallerInfoAsyncQuery startQuery()... #####"); - log("- number: " + number); + log("- number: " + /*number*/ "xxxxxxx"); log("- cookie: " + cookie); } @@ -314,7 +314,7 @@ public class CallerInfoAsyncQuery { if (PhoneNumberUtils.isUriNumber(number)) { // "number" is really a SIP address. - if (DBG) log(" - Treating number as a SIP address: " + number); + if (DBG) log(" - Treating number as a SIP address: " + /*number*/ "xxxxxxx"); // We look up SIP addresses directly in the Data table: contactRef = Data.CONTENT_URI; @@ -346,7 +346,7 @@ public class CallerInfoAsyncQuery { } if (DBG) { - log("==> contactRef: " + contactRef); + log("==> contactRef: " + sanitizeUriToString(contactRef)); log("==> selection: " + selection); if (selectionArgs != null) { for (int i = 0; i < selectionArgs.length; i++) { @@ -388,8 +388,8 @@ public class CallerInfoAsyncQuery { */ public void addQueryListener(int token, OnQueryCompleteListener listener, Object cookie) { - if (DBG) log("adding listener to query: " + mHandler.mQueryUri + " handler: " + - mHandler.toString()); + if (DBG) log("adding listener to query: " + sanitizeUriToString(mHandler.mQueryUri) + + " handler: " + mHandler.toString()); //create cookieWrapper, add query request to end of queue. CookieWrapper cw = new CookieWrapper(); @@ -423,6 +423,20 @@ public class CallerInfoAsyncQuery { mHandler = null; } + private static String sanitizeUriToString(Uri uri) { + if (uri != null) { + String uriString = uri.toString(); + int indexOfLastSlash = uriString.lastIndexOf('/'); + if (indexOfLastSlash > 0) { + return uriString.substring(0, indexOfLastSlash) + "/xxxxxxx"; + } else { + return uriString; + } + } else { + return ""; + } + } + /** * static logging method */ diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java index c80c608..438996f 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java +++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java @@ -241,7 +241,7 @@ public final class SIMRecords extends IccRecords { msisdn = number; msisdnTag = alphaTag; - if(DBG) log("Set MSISDN: " + msisdnTag +" " + msisdn); + if(DBG) log("Set MSISDN: " + msisdnTag + " " + /*msisdn*/ "xxxxxxx"); AdnRecord adn = new AdnRecord(msisdnTag, msisdn); @@ -499,7 +499,7 @@ public final class SIMRecords extends IccRecords { imsi = null; } - Log.d(LOG_TAG, "IMSI: " + imsi.substring(0, 6) + "xxxxxxxxx"); + Log.d(LOG_TAG, "IMSI: " + imsi.substring(0, 6) + "xxxxxxx"); if (mncLength == UNKNOWN) { // the SIM has told us all it knows, but it didn't know the mnc length. @@ -629,7 +629,7 @@ public final class SIMRecords extends IccRecords { msisdn = adn.getNumber(); msisdnTag = adn.getAlphaTag(); - Log.d(LOG_TAG, "MSISDN: " + msisdn); + Log.d(LOG_TAG, "MSISDN: " + /*msisdn*/ "xxxxxxx"); break; case EVENT_SET_MSISDN_DONE: diff --git a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java index c139a64..209fe06 100644 --- a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java +++ b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java @@ -57,8 +57,8 @@ abstract class SipConnectionBase extends Connection { private DisconnectCause mCause = DisconnectCause.NOT_DISCONNECTED; private PostDialState postDialState = PostDialState.NOT_STARTED; - SipConnectionBase(String calleeSipUri) { - dialString = calleeSipUri; + SipConnectionBase(String dialString) { + this.dialString = dialString; postDialString = PhoneNumberUtils.extractPostDialPortion(dialString); diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java index a951040..09d3c8e 100755 --- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java +++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java @@ -390,7 +390,8 @@ public class SipPhone extends SipPhoneBase { try { SipProfile callee = new SipProfile.Builder(calleeSipUri).build(); - SipConnection c = new SipConnection(this, callee); + SipConnection c = new SipConnection(this, callee, + originalNumber); connections.add(c); c.dial(); setState(Call.State.DIALING); @@ -581,6 +582,7 @@ public class SipPhone extends SipPhoneBase { private SipAudioCall mSipAudioCall; private Call.State mState = Call.State.IDLE; private SipProfile mPeer; + private String mOriginalNumber; // may be a PSTN number private boolean mIncoming = false; private SipAudioCallAdapter mAdapter = new SipAudioCallAdapter() { @@ -662,10 +664,16 @@ public class SipPhone extends SipPhoneBase { } }; - public SipConnection(SipCall owner, SipProfile callee) { - super(getUriString(callee)); + public SipConnection(SipCall owner, SipProfile callee, + String originalNumber) { + super(originalNumber); mOwner = owner; mPeer = callee; + mOriginalNumber = originalNumber; + } + + public SipConnection(SipCall owner, SipProfile callee) { + this(owner, callee, getUriString(callee)); } void initIncomingCall(SipAudioCall sipAudioCall, Call.State newState) { @@ -738,7 +746,10 @@ public class SipPhone extends SipPhoneBase { @Override public String getAddress() { - return getUriString(mPeer); + // Phone app uses this to query caller ID. Return the original dial + // number (which may be a PSTN number) instead of the peer's SIP + // URI. + return mOriginalNumber; } @Override diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java index 19815fd..643dbf5 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java @@ -66,7 +66,9 @@ public class TestShellActivity extends Activity implements LayoutTestController static enum DumpDataType {DUMP_AS_TEXT, EXT_REPR, NO_OP} // String constants for use with layoutTestController.overridePreferences - private final String WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED = "WebKitOfflineWebApplicationCacheEnabled"; + private final String WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED = + "WebKitOfflineWebApplicationCacheEnabled"; + private final String WEBKIT_USES_PAGE_CACHE_PREFERENCE_KEY = "WebKitUsesPageCachePreferenceKey"; public class AsyncHandler extends Handler { @Override @@ -524,8 +526,14 @@ public class TestShellActivity extends Activity implements LayoutTestController // called the layoutTestController method. Currently, we just use the // WebView for the main frame. EventSender suffers from the same // problem. - if (key.equals(WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED)) { + if (WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED.equals(key)) { mWebView.getSettings().setAppCacheEnabled(value); + } else if (WEBKIT_USES_PAGE_CACHE_PREFERENCE_KEY.equals(key)) { + // Cache the maximum possible number of pages. + mWebView.getSettings().setPageCacheCapacity(Integer.MAX_VALUE); + } else { + Log.w(LOGTAG, "LayoutTestController.overridePreference(): " + + "Unsupported preference '" + key + "'"); } } @@ -879,6 +887,7 @@ public class TestShellActivity extends Activity implements LayoutTestController settings.setDomStorageEnabled(true); settings.setWorkersEnabled(false); settings.setXSSAuditorEnabled(false); + settings.setPageCacheCapacity(0); } private WebView mWebView; diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java index 97d7cca..af8f6ea 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java @@ -394,6 +394,7 @@ public class LayoutTestsExecutor extends Activity { webViewSettings.setDomStorageEnabled(true); webViewSettings.setWorkersEnabled(false); webViewSettings.setXSSAuditorEnabled(false); + webViewSettings.setPageCacheCapacity(0); // This is asynchronous, but it gets processed by WebCore before it starts loading pages. mCurrentWebView.useMockDeviceOrientation(); @@ -565,6 +566,7 @@ public class LayoutTestsExecutor extends Activity { /** String constants for use with layoutTestController.overridePreference() */ private final String WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED = "WebKitOfflineWebApplicationCacheEnabled"; + private final String WEBKIT_USES_PAGE_CACHE_PREFERENCE_KEY = "WebKitUsesPageCachePreferenceKey"; Handler mLayoutTestControllerHandler = new Handler() { @Override @@ -609,12 +611,16 @@ public class LayoutTestsExecutor extends Activity { * WebView for the main frame. EventSender suffers from the same * problem. */ - if (msg.getData().getString("key").equals( - WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED)) { - mCurrentWebView.getSettings().setAppCacheEnabled(msg.getData().getBoolean( - "value")); + String key = msg.getData().getString("key"); + boolean value = msg.getData().getBoolean("value"); + if (WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED.equals(key)) { + mCurrentWebView.getSettings().setAppCacheEnabled(value); + } else if (WEBKIT_USES_PAGE_CACHE_PREFERENCE_KEY.equals(key)) { + // Cache the maximum possible number of pages. + mCurrentWebView.getSettings().setPageCacheCapacity(Integer.MAX_VALUE); } else { - Log.w(LOG_TAG, "MSG_OVERRIDE_PREFERENCE: unsupported preference!"); + Log.w(LOG_TAG, "LayoutTestController.overridePreference(): " + + "Unsupported preference '" + key + "'"); } break; diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java index e30cf4a..9c267d6 100644 --- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java +++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java @@ -86,6 +86,18 @@ public class NotificationTestList extends TestActivity } }, + new Test("custom intent on text view") { + public void run() { + Notification n = new Notification(R.drawable.icon1, null, + mActivityCreateTime); + n.setLatestEventInfo(NotificationTestList.this, "Persistent #1", + "This is a notification!!!", null); + n.contentView.setOnClickPendingIntent(com.android.internal.R.id.text, + makeIntent2()); + mNM.notify(1, n); + } + }, + new Test("Ticker 1 line") { public void run() { Notification n = new Notification(R.drawable.icon1, "tick tick tick", @@ -776,6 +788,12 @@ public class NotificationTestList extends TestActivity return PendingIntent.getActivity(this, 0, intent, 0); } + private PendingIntent makeIntent2() { + Intent intent = new Intent(this, StatusBarTest.class); + return PendingIntent.getActivity(this, 0, intent, 0); + } + + class StateStress extends Test { StateStress(String name, int pause, int iterations, Runnable[] tasks) { super(name); diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java index ee554b5..6f426c9 100644 --- a/voip/java/com/android/server/sip/SipService.java +++ b/voip/java/com/android/server/sip/SipService.java @@ -868,6 +868,7 @@ public final class SipService extends ISipService.Stub { case SipErrorCode.SERVER_UNREACHABLE: if (DEBUG) Log.d(TAG, " pause auto-registration"); stop(); + break; default: restartLater(); } |