diff options
107 files changed, 2374 insertions, 1110 deletions
diff --git a/api/current.txt b/api/current.txt index 3757ece06308..f33c6cb10718 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10696,6 +10696,7 @@ package android.media { field public static final int METADATA_KEY_GENRE = 6; // 0x6 field public static final int METADATA_KEY_HAS_AUDIO = 16; // 0x10 field public static final int METADATA_KEY_HAS_VIDEO = 17; // 0x11 + field public static final int METADATA_KEY_LOCATION = 23; // 0x17 field public static final int METADATA_KEY_MIMETYPE = 12; // 0xc field public static final int METADATA_KEY_NUM_TRACKS = 10; // 0xa field public static final int METADATA_KEY_TITLE = 7; // 0x7 diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f9896f7ab4e5..303f81b4cd50 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2734,8 +2734,9 @@ public final class ActivityThread { CharSequence description; } - private class ProviderRefCount { + private static final class ProviderRefCount { public int count; + ProviderRefCount(int pCount) { count = pCount; } @@ -3988,16 +3989,14 @@ public final class ActivityThread { buf.append(": "); buf.append(cpi.name); Log.i(TAG, buf.toString()); - IContentProvider cp = installProvider(context, null, cpi, false); + IContentProvider cp = installProvider(context, null, cpi, + false /*noisy*/, true /*noReleaseNeeded*/); if (cp != null) { IActivityManager.ContentProviderHolder cph = - new IActivityManager.ContentProviderHolder(cpi); + new IActivityManager.ContentProviderHolder(cpi); cph.provider = cp; + cph.noReleaseNeeded = true; results.add(cph); - // Don't ever unload this provider from the process. - synchronized(mProviderMap) { - mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000)); - } } } @@ -4008,26 +4007,22 @@ public final class ActivityThread { } } - private IContentProvider getExistingProvider(Context context, String name) { - synchronized(mProviderMap) { - final ProviderClientRecord pr = mProviderMap.get(name); - if (pr != null) { - return pr.mProvider; - } - return null; - } - } - - private IContentProvider getProvider(Context context, String name) { - IContentProvider existing = getExistingProvider(context, name); - if (existing != null) { - return existing; + public final IContentProvider acquireProvider(Context c, String name) { + IContentProvider provider = acquireExistingProvider(c, name); + if (provider != null) { + return provider; } + // There is a possible race here. Another thread may try to acquire + // the same provider at the same time. When this happens, we want to ensure + // that the first one wins. + // Note that we cannot hold the lock while acquiring and installing the + // provider since it might take a long time to run and it could also potentially + // be re-entrant in the case where the provider is in the same process. IActivityManager.ContentProviderHolder holder = null; try { holder = ActivityManagerNative.getDefault().getContentProvider( - getApplicationThread(), name); + getApplicationThread(), name); } catch (RemoteException ex) { } if (holder == null) { @@ -4035,135 +4030,136 @@ public final class ActivityThread { return null; } - IContentProvider prov = installProvider(context, holder.provider, - holder.info, true); - //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded); - if (holder.noReleaseNeeded || holder.provider == null) { - // We are not going to release the provider if it is an external - // provider that doesn't care about being released, or if it is - // a local provider running in this process. - //Slog.i(TAG, "*** NO RELEASE NEEDED"); - synchronized(mProviderMap) { - mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000)); + // Install provider will increment the reference count for us, and break + // any ties in the race. + provider = installProvider(c, holder.provider, holder.info, + true /*noisy*/, holder.noReleaseNeeded); + if (holder.provider != null && provider != holder.provider) { + if (localLOGV) { + Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous " + + "reference to the content provider"); + } + try { + ActivityManagerNative.getDefault().removeContentProvider( + getApplicationThread(), name); + } catch (RemoteException ex) { } } - return prov; - } - - public final IContentProvider acquireProvider(Context c, String name) { - IContentProvider provider = getProvider(c, name); - if(provider == null) - return null; - IBinder jBinder = provider.asBinder(); - synchronized(mProviderMap) { - ProviderRefCount prc = mProviderRefCountMap.get(jBinder); - if(prc == null) { - mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); - } else { - prc.count++; - } //end else - } //end synchronized return provider; } public final IContentProvider acquireExistingProvider(Context c, String name) { - IContentProvider provider = getExistingProvider(c, name); - if(provider == null) - return null; - IBinder jBinder = provider.asBinder(); - synchronized(mProviderMap) { + synchronized (mProviderMap) { + ProviderClientRecord pr = mProviderMap.get(name); + if (pr == null) { + return null; + } + + IContentProvider provider = pr.mProvider; + IBinder jBinder = provider.asBinder(); + + // Only increment the ref count if we have one. If we don't then the + // provider is not reference counted and never needs to be released. ProviderRefCount prc = mProviderRefCountMap.get(jBinder); - if(prc == null) { - mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); - } else { - prc.count++; - } //end else - } //end synchronized - return provider; + if (prc != null) { + prc.count += 1; + if (prc.count == 1) { + if (localLOGV) { + Slog.v(TAG, "acquireExistingProvider: " + + "snatched provider from the jaws of death"); + } + // Because the provider previously had a reference count of zero, + // it was scheduled to be removed. Cancel that. + mH.removeMessages(H.REMOVE_PROVIDER, provider); + } + } + return provider; + } } public final boolean releaseProvider(IContentProvider provider) { if(provider == null) { return false; } + IBinder jBinder = provider.asBinder(); - synchronized(mProviderMap) { + synchronized (mProviderMap) { ProviderRefCount prc = mProviderRefCountMap.get(jBinder); - if(prc == null) { - if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldn't be here"); + if (prc == null) { + // The provider has no ref count, no release is needed. return false; - } else { - prc.count--; - if(prc.count == 0) { - // Schedule the actual remove asynchronously, since we - // don't know the context this will be called in. - // TODO: it would be nice to post a delayed message, so - // if we come back and need the same provider quickly - // we will still have it available. - Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider); - mH.sendMessage(msg); - } //end if - } //end else - } //end synchronized - return true; + } + + if (prc.count == 0) { + if (localLOGV) Slog.v(TAG, "releaseProvider: ref count already 0, how?"); + return false; + } + + prc.count -= 1; + if (prc.count == 0) { + // Schedule the actual remove asynchronously, since we don't know the context + // this will be called in. + // TODO: it would be nice to post a delayed message, so + // if we come back and need the same provider quickly + // we will still have it available. + Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider); + mH.sendMessage(msg); + } + return true; + } } final void completeRemoveProvider(IContentProvider provider) { IBinder jBinder = provider.asBinder(); - String name = null; + String remoteProviderName = null; synchronized(mProviderMap) { ProviderRefCount prc = mProviderRefCountMap.get(jBinder); - if(prc != null && prc.count == 0) { - mProviderRefCountMap.remove(jBinder); - //invoke removeProvider to dereference provider - name = removeProviderLocked(provider); + if (prc == null) { + // Either no release is needed (so we shouldn't be here) or the + // provider was already released. + if (localLOGV) Slog.v(TAG, "completeRemoveProvider: release not needed"); + return; + } + + if (prc.count != 0) { + // There was a race! Some other client managed to acquire + // the provider before the removal was completed. + // Abort the removal. We will do it later. + if (localLOGV) Slog.v(TAG, "completeRemoveProvider: lost the race, " + + "provider still in use"); + return; + } + + mProviderRefCountMap.remove(jBinder); + + Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator(); + while (iter.hasNext()) { + ProviderClientRecord pr = iter.next(); + IBinder myBinder = pr.mProvider.asBinder(); + if (myBinder == jBinder) { + iter.remove(); + if (pr.mLocalProvider == null) { + myBinder.unlinkToDeath(pr, 0); + if (remoteProviderName == null) { + remoteProviderName = pr.mName; + } + } + } } } - - if (name != null) { + + if (remoteProviderName != null) { try { - if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " + - "ActivityManagerNative.removeContentProvider(" + name); + if (localLOGV) { + Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative." + + "removeContentProvider(" + remoteProviderName + ")"); + } ActivityManagerNative.getDefault().removeContentProvider( - getApplicationThread(), name); + getApplicationThread(), remoteProviderName); } catch (RemoteException e) { //do nothing content provider object is dead any way - } //end catch - } - } - - public final String removeProviderLocked(IContentProvider provider) { - if (provider == null) { - return null; + } } - IBinder providerBinder = provider.asBinder(); - - String name = null; - - // remove the provider from mProviderMap - Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator(); - while (iter.hasNext()) { - ProviderClientRecord pr = iter.next(); - IBinder myBinder = pr.mProvider.asBinder(); - if (myBinder == providerBinder) { - //find if its published by this process itself - if(pr.mLocalProvider != null) { - if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning"); - return name; - } - if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " + - "death recipient"); - //content provider is in another process - myBinder.unlinkToDeath(pr, 0); - iter.remove(); - //invoke remove only once for the very first name seen - if(name == null) { - name = pr.mName; - } - } //end if myBinder - } //end while iter - - return name; } final void removeDeadProvider(String name, IContentProvider provider) { @@ -4179,8 +4175,23 @@ public final class ActivityThread { } } + /** + * Installs the provider. + * + * Providers that are local to the process or that come from the system server + * may be installed permanently which is indicated by setting noReleaseNeeded to true. + * Other remote providers are reference counted. The initial reference count + * for all reference counted providers is one. Providers that are not reference + * counted do not have a reference count (at all). + * + * This method detects when a provider has already been installed. When this happens, + * it increments the reference count of the existing provider (if appropriate) + * and returns the existing provider. This can happen due to concurrent + * attempts to acquire the same provider. + */ private IContentProvider installProvider(Context context, - IContentProvider provider, ProviderInfo info, boolean noisy) { + IContentProvider provider, ProviderInfo info, + boolean noisy, boolean noReleaseNeeded) { ContentProvider localProvider = null; if (provider == null) { if (noisy) { @@ -4238,24 +4249,69 @@ public final class ActivityThread { } synchronized (mProviderMap) { - // Cache the pointer for the remote provider. + // There is a possibility that this thread raced with another thread to + // add the provider. If we find another thread got there first then we + // just get out of the way and return the original provider. + IBinder jBinder = provider.asBinder(); String names[] = PATTERN_SEMICOLON.split(info.authority); - for (int i=0; i<names.length; i++) { - ProviderClientRecord pr = new ProviderClientRecord(names[i], provider, - localProvider); - try { - provider.asBinder().linkToDeath(pr, 0); + for (int i = 0; i < names.length; i++) { + ProviderClientRecord pr = mProviderMap.get(names[i]); + if (pr != null) { + if (localLOGV) { + Slog.v(TAG, "installProvider: lost the race, " + + "using existing named provider"); + } + provider = pr.mProvider; + } else { + pr = new ProviderClientRecord(names[i], provider, localProvider); + if (localProvider == null) { + try { + jBinder.linkToDeath(pr, 0); + } catch (RemoteException e) { + // Provider already dead. Bail out of here without making + // any changes to the provider map or other data structures. + return null; + } + } mProviderMap.put(names[i], pr); - } catch (RemoteException e) { - return null; } } + if (localProvider != null) { - mLocalProviders.put(provider.asBinder(), - new ProviderClientRecord(null, provider, localProvider)); + ProviderClientRecord pr = mLocalProviders.get(jBinder); + if (pr != null) { + if (localLOGV) { + Slog.v(TAG, "installProvider: lost the race, " + + "using existing local provider"); + } + provider = pr.mProvider; + } else { + pr = new ProviderClientRecord(null, provider, localProvider); + mLocalProviders.put(jBinder, pr); + } } - } + if (!noReleaseNeeded) { + ProviderRefCount prc = mProviderRefCountMap.get(jBinder); + if (prc != null) { + if (localLOGV) { + Slog.v(TAG, "installProvider: lost the race, incrementing ref count"); + } + prc.count += 1; + if (prc.count == 1) { + if (localLOGV) { + Slog.v(TAG, "installProvider: " + + "snatched provider from the jaws of death"); + } + // Because the provider previously had a reference count of zero, + // it was scheduled to be removed. Cancel that. + mH.removeMessages(H.REMOVE_PROVIDER, provider); + } + } else { + mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); + } + } + } return provider; } diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 522f47760a49..0c6baebf26b9 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -901,6 +901,7 @@ public final class LoadedApk { private RuntimeException mUnbindLocation; private boolean mDied; + private boolean mForgotten; private static class ConnectionInfo { IBinder binder; @@ -959,6 +960,7 @@ public final class LoadedApk { ci.binder.unlinkToDeath(ci.deathMonitor, 0); } mActiveConnections.clear(); + mForgotten = true; } } @@ -1020,6 +1022,11 @@ public final class LoadedApk { ServiceDispatcher.ConnectionInfo info; synchronized (this) { + if (mForgotten) { + // We unbound before receiving the connection; ignore + // any connection received. + return; + } old = mActiveConnections.get(name); if (old != null && old.binder == service) { // Huh, already have this one. Oh well! diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 91398bce21f3..b1c1f3077a9d 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -635,6 +635,9 @@ public class WallpaperManager { //Log.v(TAG, "...app returning after sending offsets!"); } catch (RemoteException e) { // Ignore. + } catch (IllegalArgumentException e) { + // Since this is being posted, it's possible that this windowToken is no longer + // valid, for example, if setWallpaperOffsets is called just before rotation. } } }); diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java index 7addd4a56d18..b1d007071df8 100644 --- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java +++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java @@ -86,7 +86,7 @@ public final class BluetoothDeviceProfileState extends StateMachine { private static final int CONNECTION_ACCESS_REQUEST_REPLY = 104; private static final int CONNECTION_ACCESS_REQUEST_EXPIRY = 105; - private static final int CONNECT_OTHER_PROFILES_DELAY = 4000; // 4 secs + public static final int CONNECT_OTHER_PROFILES_DELAY = 4000; // 4 secs private static final int CONNECTION_ACCESS_REQUEST_EXPIRY_TIMEOUT = 7000; // 7 secs private static final int CONNECTION_ACCESS_UNDEFINED = -1; private static final long INIT_INCOMING_REJECT_TIMER = 1000; // 1 sec diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index fefeb9335dac..deea2b801036 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -90,7 +90,7 @@ interface IBluetooth boolean connectHeadset(String address); boolean disconnectHeadset(String address); - boolean notifyIncomingConnection(String address); + boolean notifyIncomingConnection(String address, boolean rejected); // HID profile APIs boolean connectInputDevice(in BluetoothDevice device); diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java index ad1bfb23adbe..bea652911789 100644 --- a/core/java/android/content/res/XmlBlock.java +++ b/core/java/android/content/res/XmlBlock.java @@ -484,7 +484,7 @@ final class XmlBlock { private final AssetManager mAssets; private final int mNative; - private final StringBlock mStrings; + /*package*/ final StringBlock mStrings; private boolean mOpen = true; private int mOpenCount = 1; @@ -494,9 +494,9 @@ final class XmlBlock { private static final native int nativeGetStringBlock(int obj); private static final native int nativeCreateParseState(int obj); - private static final native int nativeNext(int state); + /*package*/ static final native int nativeNext(int state); private static final native int nativeGetNamespace(int state); - private static final native int nativeGetName(int state); + /*package*/ static final native int nativeGetName(int state); private static final native int nativeGetText(int state); private static final native int nativeGetLineNumber(int state); private static final native int nativeGetAttributeCount(int state); diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 3becec0189f9..c2a757f06808 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -1111,9 +1111,21 @@ public class Camera { * Parameters#getMaxNumDetectedFaces()} returns a number larger than 0. * If the face detection has started, apps should not call this again. * - * When the face detection is running, {@link Parameters#setWhiteBalance(String)}, + * <p>When the face detection is running, {@link Parameters#setWhiteBalance(String)}, * {@link Parameters#setFocusAreas(List)}, and {@link Parameters#setMeteringAreas(List)} - * have no effect. + * have no effect. The camera uses the detected faces to do auto-white balance, + * auto exposure, and autofocus. + * + * <p>If the apps call {@link #autoFocus(AutoFocusCallback)}, the camera + * will stop sending face callbacks. The last face callback indicates the + * areas used to do autofocus. After focus completes, face detection will + * resume sending face callbacks. If the apps call {@link + * #cancelAutoFocus()}, the face callbacks will also resume.</p> + * + * <p>After calling {@link #takePicture(Camera.ShutterCallback, Camera.PictureCallback, + * Camera.PictureCallback)} or {@link #stopPreview()}, and then resuming + * preview with {@link #startPreview()}, the apps should call this method + * again to resume face detection.</p> * * @throws IllegalArgumentException if the face detection is unsupported. * @throws RuntimeException if the method fails or the face detection is @@ -1163,14 +1175,31 @@ public class Camera { * camera field of view, and (1000, 1000) represents the bottom-right of * the field of view. For example, suppose the size of the viewfinder UI * is 800x480. The rect passed from the driver is (-1000, -1000, 0, 0). - * The corresponding viewfinder rect should be (0, 0, 400, 240). The - * width and height of the rect will not be 0 or negative. The - * coordinates can be smaller than -1000 or bigger than 1000. But at - * least one vertex will be within (-1000, -1000) and (1000, 1000). + * The corresponding viewfinder rect should be (0, 0, 400, 240). It is + * guaranteed left < right and top < bottom. The coordinates can be + * smaller than -1000 or bigger than 1000. But at least one vertex will + * be within (-1000, -1000) and (1000, 1000). * * <p>The direction is relative to the sensor orientation, that is, what * the sensor sees. The direction is not affected by the rotation or - * mirroring of {@link #setDisplayOrientation(int)}.</p> + * mirroring of {@link #setDisplayOrientation(int)}. The face bounding + * rectangle does not provide any information about face orientation.</p> + * + * <p>Here is the matrix to convert driver coordinates to View coordinates + * in pixels.</p> + * <pre> + * Matrix matrix = new Matrix(); + * CameraInfo info = CameraHolder.instance().getCameraInfo()[cameraId]; + * // Need mirror for front camera. + * boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); + * matrix.setScale(mirror ? -1 : 1, 1); + * // This is the value for android.hardware.Camera.setDisplayOrientation. + * matrix.postRotate(displayOrientation); + * // Camera driver coordinates range from (-1000, -1000) to (1000, 1000). + * // UI coordinates range from (0, 0) to (width, height). + * matrix.postScale(view.getWidth() / 2000f, view.getHeight() / 2000f); + * matrix.postTranslate(view.getWidth() / 2f, view.getHeight() / 2f); + * </pre> * * @see #startFaceDetection() */ diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 016af58da74a..0b93ad03fe5f 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -32,7 +32,7 @@ import android.nfc.INfcTag; interface INfcAdapter { INfcTag getNfcTagInterface(); - INfcAdapterExtras getNfcAdapterExtrasInterface(); + INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg); int getState(); boolean disable(); diff --git a/core/java/android/nfc/INfcAdapterExtras.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl index 0c2a2fd065b2..2b9d4f04951a 100644 --- a/core/java/android/nfc/INfcAdapterExtras.aidl +++ b/core/java/android/nfc/INfcAdapterExtras.aidl @@ -23,10 +23,10 @@ import android.os.Bundle; * {@hide} */ interface INfcAdapterExtras { - Bundle open(IBinder b); - Bundle close(); - Bundle transceive(in byte[] data_in); - int getCardEmulationRoute(); - void setCardEmulationRoute(int route); - void authenticate(in byte[] token); + Bundle open(in String pkg, IBinder b); + Bundle close(in String pkg, IBinder b); + Bundle transceive(in String pkg, in byte[] data_in); + int getCardEmulationRoute(in String pkg); + void setCardEmulationRoute(in String pkg, int route); + void authenticate(in String pkg, in byte[] token); } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index fe0106dc52c4..a9f1685480c7 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -16,6 +16,8 @@ package android.nfc; +import java.util.HashMap; + import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Activity; @@ -197,15 +199,21 @@ public final class NfcAdapter { static INfcTag sTagService; /** - * NfcAdapter is currently a singleton, and does not require a context. - * However all the public API's are future-proofed to require a context. - * If we start using that then we'll need to keep a HashMap of - * Context.getApplicationContext() -> NfcAdapter, such that NfcAdapter - * is a singleton within each application context. + * The NfcAdapter object for each application context. + * There is a 1-1 relationship between application context and + * NfcAdapter object. + */ + static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class + + /** + * NfcAdapter used with a null context. This ctor was deprecated but we have + * to support it for backwards compatibility. New methods that require context + * might throw when called on the null-context NfcAdapter. */ - static NfcAdapter sSingleton; // protected by NfcAdapter.class + static NfcAdapter sNullContextNfcAdapter; // protected by NfcAdapter.class final NfcActivityManager mNfcActivityManager; + final Context mContext; /** * A callback to be invoked when the system successfully delivers your {@link NdefMessage} @@ -280,12 +288,12 @@ public final class NfcAdapter { } /** - * Returns the singleton, or throws if NFC is not available. + * Returns the NfcAdapter for application context, + * or throws if NFC is not available. + * @hide */ - static synchronized NfcAdapter getSingleton() { + public static synchronized NfcAdapter getNfcAdapter(Context context) { if (!sIsInitialized) { - sIsInitialized = true; - /* is this device meant to have NFC */ if (!hasNfcFeature()) { Log.v(TAG, "this device does not have NFC support"); @@ -303,12 +311,21 @@ public final class NfcAdapter { Log.e(TAG, "could not retrieve NFC Tag service"); throw new UnsupportedOperationException(); } - sSingleton = new NfcAdapter(); + + sIsInitialized = true; + } + if (context == null) { + if (sNullContextNfcAdapter == null) { + sNullContextNfcAdapter = new NfcAdapter(null); + } + return sNullContextNfcAdapter; } - if (sSingleton == null) { - throw new UnsupportedOperationException(); + NfcAdapter adapter = sNfcAdapters.get(context); + if (adapter == null) { + adapter = new NfcAdapter(context); + sNfcAdapters.put(context, adapter); } - return sSingleton; + return adapter; } /** get handle to NFC service interface */ @@ -336,6 +353,10 @@ public final class NfcAdapter { * @return the default NFC adapter, or null if no NFC adapter exists */ public static NfcAdapter getDefaultAdapter(Context context) { + if (context == null) { + throw new IllegalArgumentException("context cannot be null"); + } + context = context.getApplicationContext(); /* use getSystemService() instead of just instantiating to take * advantage of the context's cached NfcManager & NfcAdapter */ NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); @@ -343,25 +364,30 @@ public final class NfcAdapter { } /** - * Get a handle to the default NFC Adapter on this Android device. - * <p> - * Most Android devices will only have one NFC Adapter (NFC Controller). - * - * @return the default NFC adapter, or null if no NFC adapter exists + * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p> + * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required + * for many NFC API methods. Those methods will fail when called on an NfcAdapter + * object created from this method.<p> * @deprecated use {@link #getDefaultAdapter(Context)} */ @Deprecated public static NfcAdapter getDefaultAdapter() { Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " + "NfcAdapter.getDefaultAdapter(Context) instead", new Exception()); - return getSingleton(); + + return NfcAdapter.getNfcAdapter(null); + } + + NfcAdapter(Context context) { + mContext = context; + mNfcActivityManager = new NfcActivityManager(this); } /** - * Does not currently need a context. + * @hide */ - NfcAdapter() { - mNfcActivityManager = new NfcActivityManager(this); + public Context getContext() { + return mContext; } /** @@ -875,8 +901,12 @@ public final class NfcAdapter { * @hide */ public INfcAdapterExtras getNfcAdapterExtrasInterface() { + if (mContext == null) { + throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " + + " NFC extras APIs"); + } try { - return sService.getNfcAdapterExtrasInterface(); + return sService.getNfcAdapterExtrasInterface(mContext.getPackageName()); } catch (RemoteException e) { attemptDeadServiceRecovery(e); return null; diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java index 300ab45460e2..6ec2e219d5c4 100644 --- a/core/java/android/nfc/NfcManager.java +++ b/core/java/android/nfc/NfcManager.java @@ -39,8 +39,9 @@ public final class NfcManager { */ public NfcManager(Context context) { NfcAdapter adapter; + context = context.getApplicationContext(); try { - adapter = NfcAdapter.getSingleton(); + adapter = NfcAdapter.getNfcAdapter(context); } catch (UnsupportedOperationException e) { adapter = null; } diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 821b6df5fd15..83acef83ad1d 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -187,6 +187,16 @@ public final class ContactsContract { public static final String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query"; /** + * A boolean parameter for {@link CommonDataKinds.Phone#CONTENT_URI}, + * {@link CommonDataKinds.Email#CONTENT_URI}, and + * {@link CommonDataKinds.StructuredPostal#CONTENT_URI}. + * This enables a content provider to remove duplicate entries in results. + * + * @hide + */ + public static final String REMOVE_DUPLICATE_ENTRIES = "remove_duplicate_entries"; + + /** * <p> * API for obtaining a pre-authorized version of a URI that normally requires special * permission (beyond READ_CONTACTS) to read. The caller obtaining the pre-authorized URI diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 1b473ece19a8..aa62cd70190e 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -784,11 +784,12 @@ class BluetoothEventLoop { // machine. We don't handle AVCTP signals currently. We only send // intents for AVDTP state changes. We need to handle both of them in // some cases. For now, just don't move to incoming state in this case. - mBluetoothService.notifyIncomingA2dpConnection(address); + mBluetoothService.notifyIncomingA2dpConnection(address, true); } else { Log.i(TAG, "" + authorized + "Incoming A2DP / AVRCP connection from " + address); mA2dp.allowIncomingConnect(device, authorized); + mBluetoothService.notifyIncomingA2dpConnection(address, false); } } else if (BluetoothUuid.isInputDevice(uuid)) { // We can have more than 1 input device connected. diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index 9ca58477dd41..d604a01a759e 100755 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -89,7 +89,7 @@ public class BluetoothService extends IBluetooth.Stub { private int mNativeData; private BluetoothEventLoop mEventLoop; - private BluetoothHeadset mBluetoothHeadset; + private BluetoothHeadset mHeadsetProxy; private BluetoothInputDevice mInputDevice; private BluetoothPan mPan; private boolean mIsAirplaneSensitive; @@ -605,6 +605,7 @@ public class BluetoothService extends IBluetooth.Stub { } mBondState.initBondState(); initProfileState(); + getProfileProxy(); } /** @@ -1766,8 +1767,8 @@ public class BluetoothService extends IBluetooth.Stub { private void dumpHeadsetService(PrintWriter pw) { pw.println("\n--Headset Service--"); - if (mBluetoothHeadset != null) { - List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); + if (mHeadsetProxy != null) { + List<BluetoothDevice> deviceList = mHeadsetProxy.getConnectedDevices(); if (deviceList.size() == 0) { pw.println("No headsets connected"); } else { @@ -1775,21 +1776,20 @@ public class BluetoothService extends IBluetooth.Stub { pw.println("\ngetConnectedDevices[0] = " + device); dumpHeadsetConnectionState(pw, device); pw.println("getBatteryUsageHint() = " + - mBluetoothHeadset.getBatteryUsageHint(device)); + mHeadsetProxy.getBatteryUsageHint(device)); } deviceList.clear(); - deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] { + deviceList = mHeadsetProxy.getDevicesMatchingConnectionStates(new int[] { BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); pw.println("--Connected and Disconnected Headsets"); for (BluetoothDevice device: deviceList) { pw.println(device); - if (mBluetoothHeadset.isAudioConnected(device)) { + if (mHeadsetProxy.isAudioConnected(device)) { pw.println("SCO audio connected to device:" + device); } } } - mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); } private void dumpInputDeviceProfile(PrintWriter pw) { @@ -1824,7 +1824,6 @@ public class BluetoothService extends IBluetooth.Stub { pw.println(device); } } - mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset); } private void dumpPanProfile(PrintWriter pw) { @@ -1862,7 +1861,7 @@ public class BluetoothService extends IBluetooth.Stub { private void dumpHeadsetConnectionState(PrintWriter pw, BluetoothDevice device) { - switch (mBluetoothHeadset.getConnectionState(device)) { + switch (mHeadsetProxy.getConnectionState(device)) { case BluetoothHeadset.STATE_CONNECTING: pw.println("getConnectionState() = STATE_CONNECTING"); break; @@ -1884,7 +1883,6 @@ public class BluetoothService extends IBluetooth.Stub { Integer pid = mServiceRecordToPid.get(handle).first; pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); } - mAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothHeadset); } private void dumpAclConnectedDevices(PrintWriter pw) { @@ -1927,11 +1925,16 @@ public class BluetoothService extends IBluetooth.Stub { } } + private void getProfileProxy() { + mAdapter.getProfileProxy(mContext, + mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); + } + private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET) { - mBluetoothHeadset = (BluetoothHeadset) proxy; + mHeadsetProxy = (BluetoothHeadset) proxy; } else if (profile == BluetoothProfile.INPUT_DEVICE) { mInputDevice = (BluetoothInputDevice) proxy; } else if (profile == BluetoothProfile.PAN) { @@ -1940,7 +1943,7 @@ public class BluetoothService extends IBluetooth.Stub { } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET) { - mBluetoothHeadset = null; + mHeadsetProxy = null; } else if (profile == BluetoothProfile.INPUT_DEVICE) { mInputDevice = null; } else if (profile == BluetoothProfile.PAN) { @@ -2424,25 +2427,43 @@ public class BluetoothService extends IBluetooth.Stub { } } - public boolean notifyIncomingConnection(String address) { - BluetoothDeviceProfileState state = - mDeviceProfileState.get(address); + public boolean notifyIncomingConnection(String address, boolean rejected) { + BluetoothDeviceProfileState state = mDeviceProfileState.get(address); if (state != null) { Message msg = new Message(); - msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING; - state.sendMessage(msg); + if (rejected) { + if (mA2dpService.getPriority(getRemoteDevice(address)) >= + BluetoothProfile.PRIORITY_ON) { + msg.what = BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES; + msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; + state.sendMessageDelayed(msg, + BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES_DELAY); + } + } else { + msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING; + state.sendMessage(msg); + } return true; } return false; } - /*package*/ boolean notifyIncomingA2dpConnection(String address) { - BluetoothDeviceProfileState state = - mDeviceProfileState.get(address); + /*package*/ boolean notifyIncomingA2dpConnection(String address, boolean rejected) { + BluetoothDeviceProfileState state = mDeviceProfileState.get(address); if (state != null) { Message msg = new Message(); - msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING; - state.sendMessage(msg); + if (rejected) { + if (mHeadsetProxy.getPriority(getRemoteDevice(address)) >= + BluetoothProfile.PRIORITY_ON) { + msg.what = BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES; + msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING; + state.sendMessageDelayed(msg, + BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES_DELAY); + } + } else { + msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING; + state.sendMessage(msg); + } return true; } return false; diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 7249497120b2..ec2f55bc4819 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -3097,10 +3097,7 @@ public class WebView extends AbsoluteLayout // Special-case layer scrolling so that we do not trigger normal scroll // updating. if (mTouchMode == TOUCH_DRAG_LAYER_MODE) { - nativeScrollLayer(mScrollingLayer, scrollX, scrollY); - mScrollingLayerRect.left = scrollX; - mScrollingLayerRect.top = scrollY; - invalidate(); + scrollLayerTo(scrollX, scrollY); return; } mInOverScrollMode = false; @@ -3603,9 +3600,7 @@ public class WebView extends AbsoluteLayout mScrollY = y; } else { // Update the layer position instead of WebView. - nativeScrollLayer(mScrollingLayer, x, y); - mScrollingLayerRect.left = x; - mScrollingLayerRect.top = y; + scrollLayerTo(x, y); } abortAnimation(); nativeSetIsScrolling(false); @@ -3624,6 +3619,17 @@ public class WebView extends AbsoluteLayout } } + private void scrollLayerTo(int x, int y) { + if (x == mScrollingLayerRect.left && y == mScrollingLayerRect.top) { + return; + } + nativeScrollLayer(mScrollingLayer, x, y); + mScrollingLayerRect.left = x; + mScrollingLayerRect.top = y; + onScrollChanged(mScrollX, mScrollY, mScrollX, mScrollY); + invalidate(); + } + private static int computeDuration(int dx, int dy) { int distance = Math.max(Math.abs(dx), Math.abs(dy)); int duration = distance * 1000 / STD_SPEED; @@ -8309,12 +8315,8 @@ public class WebView extends AbsoluteLayout if (mScrollingLayer == 0) { pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0); } else { - mScrollingLayerRect.left += mAutoScrollX; - mScrollingLayerRect.top += mAutoScrollY; - nativeScrollLayer(mScrollingLayer, - mScrollingLayerRect.left, - mScrollingLayerRect.top); - invalidate(); + scrollLayerTo(mScrollingLayerRect.left + mAutoScrollX, + mScrollingLayerRect.top + mAutoScrollY); } sendEmptyMessageDelayed( SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL); diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java index fd2abc249d95..326587e6e7cb 100644 --- a/core/java/android/widget/EdgeEffect.java +++ b/core/java/android/widget/EdgeEffect.java @@ -129,7 +129,7 @@ public class EdgeEffect { mEdge = res.getDrawable(R.drawable.overscroll_edge); mGlow = res.getDrawable(R.drawable.overscroll_glow); - mMinWidth = (int) (context.getResources().getDisplayMetrics().density * MIN_WIDTH + 0.5f); + mMinWidth = (int) (res.getDisplayMetrics().density * MIN_WIDTH + 0.5f); mInterpolator = new DecelerateInterpolator(); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index bc8721accf4f..f422f60cf21a 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; +import android.content.res.CompatibilityInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; @@ -130,7 +131,6 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.InputMethodSubtype; import android.view.textservice.SpellCheckerSubtype; import android.view.textservice.TextServicesManager; import android.widget.AdapterView.OnItemClickListener; @@ -449,18 +449,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener super(context, attrs, defStyle); mText = ""; + final Resources res = getResources(); + final CompatibilityInfo compat = res.getCompatibilityInfo(); + mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - mTextPaint.density = getResources().getDisplayMetrics().density; - mTextPaint.setCompatibilityScaling( - getResources().getCompatibilityInfo().applicationScale); + mTextPaint.density = res.getDisplayMetrics().density; + mTextPaint.setCompatibilityScaling(compat.applicationScale); // If we get the paint from the skin, we should set it to left, since // the layout always wants it to be left. // mTextPaint.setTextAlign(Paint.Align.LEFT); mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mHighlightPaint.setCompatibilityScaling( - getResources().getCompatibilityInfo().applicationScale); + mHighlightPaint.setCompatibilityScaling(compat.applicationScale); mMovement = getDefaultMovementMethod(); mTransformation = null; @@ -5340,7 +5341,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener switch (keyCode) { case KeyEvent.KEYCODE_ENTER: - mEnterKeyIsDown = true; if (event.hasNoModifiers()) { // When mInputContentType is set, we know that we are // running in a "modern" cupcake environment, so don't need @@ -5372,7 +5372,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; case KeyEvent.KEYCODE_DPAD_CENTER: - mDPadCenterIsDown = true; if (event.hasNoModifiers()) { if (shouldAdvanceFocusOnEnter()) { return 0; @@ -5486,7 +5485,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: - mDPadCenterIsDown = false; if (event.hasNoModifiers()) { /* * If there is a click listener, just call through to @@ -5511,7 +5509,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return super.onKeyUp(keyCode, event); case KeyEvent.KEYCODE_ENTER: - mEnterKeyIsDown = false; if (event.hasNoModifiers()) { if (mInputContentType != null && mInputContentType.onEditorActionListener != null @@ -8970,17 +8967,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private long getLastTouchOffsets() { - int minOffset, maxOffset; - - if (mContextMenuTriggeredByKey) { - minOffset = getSelectionStart(); - maxOffset = getSelectionEnd(); - } else { - SelectionModifierCursorController selectionController = getSelectionController(); - minOffset = selectionController.getMinTouchOffset(); - maxOffset = selectionController.getMaxTouchOffset(); - } - + SelectionModifierCursorController selectionController = getSelectionController(); + final int minOffset = selectionController.getMinTouchOffset(); + final int maxOffset = selectionController.getMaxTouchOffset(); return packRangeInLong(minOffset, maxOffset); } @@ -9073,12 +9062,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private static final int ID_COPY = android.R.id.copy; private static final int ID_PASTE = android.R.id.paste; - private class MenuHandler implements MenuItem.OnMenuItemClickListener { - public boolean onMenuItemClick(MenuItem item) { - return onTextContextMenuItem(item.getItemId()); - } - } - /** * Called when a context menu option for the text view is selected. Currently * this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut}, @@ -11478,12 +11461,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private boolean mSelectionControllerEnabled; private boolean mInBatchEditControllers; - // These are needed to desambiguate a long click. If the long click comes from ones of these, we - // select from the current cursor position. Otherwise, select from long pressed position. - private boolean mDPadCenterIsDown = false; - private boolean mEnterKeyIsDown = false; - private boolean mContextMenuTriggeredByKey = false; - private boolean mSelectAllOnFocus = false; private int mGravity = Gravity.TOP | Gravity.START; diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 4714be8df3d9..b689f536c3cb 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -537,7 +537,7 @@ public class ActionBarView extends AbsActionBarView { if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) { final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0; - final int vis = showHome ? VISIBLE : GONE; + final int vis = showHome && mExpandedActionView == null ? VISIBLE : GONE; mHomeLayout.setVisibility(vis); if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) { diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java index 6f24ebaea2ba..daefc9a3046a 100644 --- a/core/java/com/android/internal/widget/DigitalClock.java +++ b/core/java/com/android/internal/widget/DigitalClock.java @@ -106,7 +106,8 @@ public class DigitalClock extends RelativeLayout { private String mAmString, mPmString; AmPm(View parent, Typeface tf) { - mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm); + // No longer used, uncomment if we decide to use AM/PM indicator again + // mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm); if (mAmPmTextView != null && tf != null) { mAmPmTextView.setTypeface(tf); } diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp index ffcd1a0c0ab6..de2d8c48b662 100644 --- a/core/jni/android/graphics/SurfaceTexture.cpp +++ b/core/jni/android/graphics/SurfaceTexture.cpp @@ -212,10 +212,10 @@ static void SurfaceTexture_setDefaultBufferSize( surfaceTexture->setDefaultBufferSize(width, height); } -static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz) +static jint SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz) { sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); - surfaceTexture->updateTexImage(); + return surfaceTexture->updateTexImage(); } static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz, @@ -246,7 +246,7 @@ static JNINativeMethod gSurfaceTextureMethods[] = { {"nativeInit", "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init }, {"nativeFinalize", "()V", (void*)SurfaceTexture_finalize }, {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize }, - {"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage }, + {"nativeUpdateTexImage", "()I", (void*)SurfaceTexture_updateTexImage }, {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix }, {"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp }, {"nativeRelease", "()V", (void*)SurfaceTexture_release }, diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index 79aa43b2f90c..7076e2a84eb3 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -249,7 +249,7 @@ TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) : flags(other.flags), hinting(other.hinting) { if (other.text) { - textCopy.setTo(other.text); + textCopy.setTo(other.text, other.contextCount); } } diff --git a/core/res/res/drawable-hdpi/transportcontrol_bg.9.png b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png Binary files differnew file mode 100644 index 000000000000..ebd6f8a1fe9c --- /dev/null +++ b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png diff --git a/core/res/res/drawable-mdpi/transportcontrol_bg.9.png b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png Binary files differnew file mode 100644 index 000000000000..d5a339fe51d1 --- /dev/null +++ b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png diff --git a/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png Binary files differnew file mode 100644 index 000000000000..b690a2a029dc --- /dev/null +++ b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml index b58f0812801f..f9728434a838 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml @@ -17,45 +17,69 @@ */ --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - - <View - android:layout_width="match_parent" - android:layout_height="0dip" - android:layout_weight="1" - /> + android:layout_height="match_parent"> + <!-- left side: status and music --> <RelativeLayout - android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="match_parent" + android:layout_weight="1" + android:layout_width="0dip" + android:gravity="center"> - <!-- left side: status --> - <include layout="@layout/keyguard_screen_status_land" - android:layout_width="wrap_content" + <RelativeLayout android:id="@+id/transport_bg_protect" + android:layout_width="512dip" android:layout_height="wrap_content" - android:layout_marginLeft="102dip" - android:paddingTop="50dip" - android:layout_centerVertical="true" - android:layout_alignParentLeft="true"/> + android:layout_marginBottom="24dip"> + + <!-- Music transport control underneath --> + <include android:id="@+id/transport" + layout="@layout/keyguard_transport_control" + android:layout_row="0" + android:layout_column="0" + android:layout_rowSpan="3" + android:layout_columnSpan="1" + android:layout_gravity="fill" + android:layout_width="match_parent" + android:layout_height="512dip" + /> + + <!-- Status --> + <include layout="@layout/keyguard_screen_status_land" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="50dip" + android:layout_marginTop="50dip" + android:layout_marginBottom="50dip" + android:layout_marginRight="64dip" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true"/> + + </RelativeLayout> + + </RelativeLayout> + + <!-- right side: password --> + <LinearLayout + android:layout_width="0dip" + android:layout_weight="1" + android:layout_height="match_parent" + android:orientation="vertical" + android:gravity="center"> - <!-- right side: password --> <LinearLayout - android:layout_width="330dip" - android:layout_height="wrap_content" android:orientation="vertical" - android:layout_alignParentRight="true" - android:layout_centerVertical="true" - android:layout_marginRight="155dip"> - + android:layout_width="330dip" + android:layout_height="wrap_content"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" + android:layout_gravity="center" android:background="@drawable/lockscreen_password_field_dark"> <EditText android:id="@+id/passwordEntry" @@ -88,6 +112,7 @@ android:visibility="gone" /> + <!-- The IME switcher button is only shown in ASCII password mode (not PIN) --> <ImageView android:id="@+id/switch_ime_button" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -103,33 +128,29 @@ <!-- Numeric keyboard --> <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard" - android:layout_width="330dip" + android:layout_width="match_parent" android:layout_height="330dip" android:background="#40000000" android:layout_marginTop="5dip" android:keyBackground="@drawable/btn_keyboard_key_ics" android:visibility="gone" /> - </LinearLayout> - </RelativeLayout> + <!-- Emergency call button. Generally not used on tablet devices. --> + <Button + android:id="@+id/emergencyCallButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:drawableLeft="@drawable/ic_emergency" + android:drawablePadding="8dip" + android:text="@string/lockscreen_emergency_call" + android:visibility="gone" + style="@style/Widget.Button.Transparent" + /> - <View - android:layout_width="match_parent" - android:layout_height="0dip" - android:layout_weight="1" - /> - - <!-- emergency call button NOT CURRENTLY USED --> - <Button - android:id="@+id/emergencyCallButton" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:drawableLeft="@drawable/ic_emergency" - android:drawablePadding="8dip" - android:text="@string/lockscreen_emergency_call" - android:visibility="gone" - style="@style/Widget.Button.Transparent" - /> + </LinearLayout> + + </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml index cadb5f8b02fc..8b65b223e4e6 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml @@ -16,23 +16,48 @@ ** limitations under the License. */ --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> + android:layout_height="match_parent"> - <!-- top: status --> + <!-- top: status and emergency/forgot pattern buttons --> <RelativeLayout - android:layout_width="match_parent" - android:layout_height="0dip" - android:layout_weight="1"> - <include layout="@layout/keyguard_screen_status_port" - android:layout_width="wrap_content" + android:layout_height="0dip" + android:layout_weight="1" + android:layout_width="match_parent" + android:gravity="center"> + + <RelativeLayout android:id="@+id/transport_bg_protect" + android:layout_width="512dip" android:layout_height="wrap_content" - android:layout_marginTop="134dip" - android:layout_marginLeft="266dip" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true"/> + android:gravity="center"> + + <!-- Music transport control --> + <include android:id="@+id/transport" + layout="@layout/keyguard_transport_control" + android:layout_row="0" + android:layout_column="0" + android:layout_rowSpan="3" + android:layout_columnSpan="1" + android:layout_gravity="fill" + android:layout_width="match_parent" + android:layout_height="512dip" + /> + + <include layout="@layout/keyguard_screen_status_port" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="50dip" + android:layout_marginTop="50dip" + android:layout_marginBottom="100dip" + android:layout_marginRight="64dip" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true"/> + + </RelativeLayout> + </RelativeLayout> <!-- bottom: password --> diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml index 3a7c1e1c4bf9..4fafc3cc0594 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml @@ -23,15 +23,14 @@ android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="left" - > + android:gravity="right"> <TextView android:id="@+id/carrier" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="17sp" + android:textSize="16sp" android:drawablePadding="4dip" android:layout_marginTop="32dip" android:singleLine="true" @@ -72,19 +71,6 @@ android:layout_marginBottom="6dip" /> - <TextView android:id="@+id/am_pm" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/timeDisplayBackground" - android:layout_alignBaseline="@id/timeDisplayBackground" - android:singleLine="true" - android:ellipsize="none" - android:textSize="30sp" - android:layout_marginLeft="8dip" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="@color/lockscreen_clock_am_pm" - /> - </com.android.internal.widget.DigitalClock> <LinearLayout @@ -99,15 +85,16 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="17sp"/> + android:textSize="16sp"/> <TextView android:id="@+id/alarm_status" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginLeft="30dip" + android:layout_marginLeft="16dip" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="17sp"/> + android:drawablePadding="4dip" + android:textSize="16sp"/> </LinearLayout> @@ -117,7 +104,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dip" - android:textSize="17sp" + android:textSize="16sp" android:textAppearance="?android:attr/textAppearanceMedium" /> @@ -127,7 +114,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="17sp" + android:textSize="16sp" android:layout_marginTop="20dip" android:singleLine="false" android:textColor="@color/lockscreen_owner_info" diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml index c02341e4bc23..dfab3e3f56d3 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml @@ -23,9 +23,8 @@ android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginLeft="140dip" android:layout_marginTop="20dip" - android:gravity="left" + android:gravity="right" > <TextView @@ -33,7 +32,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="17sp" + android:textSize="16sp" android:drawablePadding="4dip" android:layout_marginTop="32dip" android:singleLine="true" @@ -73,19 +72,6 @@ android:layout_alignTop="@id/timeDisplayBackground" /> - <TextView android:id="@+id/am_pm" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/timeDisplayBackground" - android:layout_alignBaseline="@id/timeDisplayBackground" - android:singleLine="true" - android:ellipsize="none" - android:textSize="30sp" - android:layout_marginLeft="8dip" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="@color/lockscreen_clock_am_pm" - /> - </com.android.internal.widget.DigitalClock> <LinearLayout @@ -100,15 +86,16 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="17sp"/> + android:textSize="16sp"/> <TextView android:id="@+id/alarm_status" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginLeft="30dip" + android:layout_marginLeft="16dip" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="17sp"/> + android:drawablePadding="4dip" + android:textSize="16sp"/> </LinearLayout> @@ -117,7 +104,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dip" - android:textSize="17sp" + android:textSize="16sp" android:textAppearance="?android:attr/textAppearanceMedium" /> @@ -128,7 +115,7 @@ android:layout_height="wrap_content" android:layout_marginTop="20dip" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="17sp" + android:textSize="16sp" android:singleLine="false" android:visibility="invisible" android:textColor="@color/lockscreen_owner_info" diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml index 23b2fcb891e5..73dadb44e58c 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml @@ -30,15 +30,40 @@ <!-- top: status --> <RelativeLayout - android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" - android:orientation="vertical"> - <include layout="@layout/keyguard_screen_status_port" - android:layout_width="wrap_content" + android:layout_width="match_parent" + android:gravity="center"> + + <RelativeLayout android:id="@+id/transport_bg_protect" + android:layout_width="512dip" android:layout_height="wrap_content" - android:layout_marginTop="134dip" - android:layout_marginLeft="266dip"/> + android:gravity="center"> + + <!-- Music transport control --> + <include android:id="@+id/transport" + layout="@layout/keyguard_transport_control" + android:layout_row="0" + android:layout_column="0" + android:layout_rowSpan="3" + android:layout_columnSpan="1" + android:layout_gravity="fill" + android:layout_width="match_parent" + android:layout_height="512dip" + /> + + <include layout="@layout/keyguard_screen_status_port" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="50dip" + android:layout_marginTop="50dip" + android:layout_marginBottom="100dip" + android:layout_marginRight="64dip" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true"/> + + </RelativeLayout> + </RelativeLayout> <LinearLayout diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml index 66223f2f817d..10b1ace1105e 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml @@ -27,19 +27,40 @@ android:orientation="horizontal" android:id="@+id/root"> - <!-- left side: status --> + <!-- left side: status and music --> <RelativeLayout android:layout_height="match_parent" android:layout_weight="1" - android:layout_width="0dip"> + android:layout_width="0dip" + android:gravity="center"> - <include layout="@layout/keyguard_screen_status_land" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="102dip" - android:layout_marginTop="320dip" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true"/> + <RelativeLayout android:id="@+id/transport_bg_protect" + android:layout_width="512dip" + android:layout_height="wrap_content"> + + <!-- Music transport control underneath --> + <include android:id="@+id/transport" + layout="@layout/keyguard_transport_control" + android:layout_row="0" + android:layout_column="0" + android:layout_rowSpan="3" + android:layout_columnSpan="1" + android:layout_gravity="fill" + android:layout_width="match_parent" + android:layout_height="512dip" + /> + + <include layout="@layout/keyguard_screen_status_land" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="50dip" + android:layout_marginTop="50dip" + android:layout_marginBottom="82dip" + android:layout_marginRight="64dip" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true"/> + + </RelativeLayout> </RelativeLayout> diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml index 7ac41b5f1913..70d18cc7c1ab 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml @@ -27,19 +27,41 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - <!-- left side: status --> + <!-- left side: status and music --> <RelativeLayout android:layout_height="match_parent" android:layout_weight="1" - android:layout_width="0dip"> + android:layout_width="0dip" + android:gravity="center"> - <include layout="@layout/keyguard_screen_status_land" - android:layout_width="wrap_content" + <RelativeLayout android:id="@+id/transport_bg_protect" + android:layout_width="512dip" android:layout_height="wrap_content" - android:layout_marginLeft="102dip" - android:layout_marginTop="320dip" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true"/> + android:layout_marginBottom="24dip"> + + <!-- Music transport control underneath --> + <include android:id="@+id/transport" + layout="@layout/keyguard_transport_control" + android:layout_row="0" + android:layout_column="0" + android:layout_rowSpan="3" + android:layout_columnSpan="1" + android:layout_gravity="fill" + android:layout_width="match_parent" + android:layout_height="512dip" + /> + + <include layout="@layout/keyguard_screen_status_land" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="50dip" + android:layout_marginTop="50dip" + android:layout_marginBottom="50dip" + android:layout_marginRight="64dip" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true"/> + + </RelativeLayout> </RelativeLayout> @@ -58,22 +80,23 @@ <!-- Emergency and forgot pattern buttons. --> <LinearLayout + android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/lockPattern" android:layout_alignLeft="@id/lockPattern" android:layout_alignRight="@id/lockPattern" android:layout_marginTop="28dip" - android:layout_marginLeft="28dip" - android:layout_marginRight="28dip" - android:orientation="horizontal"> + android:gravity="center" + style="?android:attr/buttonBarStyle" + android:weightSum="2"> <Button android:id="@+id/forgotPatternButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - style="@style/Widget.Button.Transparent" - android:drawableLeft="@drawable/ic_emergency" + style="?android:attr/buttonBarButtonStyle" + android:drawableLeft="@drawable/lockscreen_forgot_password_button" android:drawablePadding="8dip" android:text="@string/lockscreen_forgot_pattern_button_text" android:visibility="gone" @@ -83,7 +106,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - style="@style/Widget.Button.Transparent" + style="?android:attr/buttonBarButtonStyle" android:drawableLeft="@drawable/ic_emergency" android:drawablePadding="8dip" android:text="@string/lockscreen_emergency_call" diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml index 1f6058fc2fab..7a623ce1b777 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml @@ -23,32 +23,72 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - <!-- top: status and emergency/forgot pattern buttons --> - <LinearLayout + <!-- top: status --> + <RelativeLayout android:layout_height="0dip" android:layout_weight="1" android:layout_width="match_parent" - android:orientation="vertical"> + android:gravity="center"> - <include layout="@layout/keyguard_screen_status_port" - android:layout_width="wrap_content" + <RelativeLayout android:id="@+id/transport_bg_protect" + android:layout_width="512dip" android:layout_height="wrap_content" - android:layout_marginTop="134dip" - android:layout_marginLeft="266dip"/> + android:gravity="center"> + + <!-- Music transport control --> + <include android:id="@+id/transport" + layout="@layout/keyguard_transport_control" + android:layout_row="0" + android:layout_column="0" + android:layout_rowSpan="3" + android:layout_columnSpan="1" + android:layout_gravity="fill" + android:layout_width="match_parent" + android:layout_height="512dip" + /> + + <include layout="@layout/keyguard_screen_status_land" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="50dip" + android:layout_marginTop="50dip" + android:layout_marginBottom="100dip" + android:layout_marginRight="64dip" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true"/> + + </RelativeLayout> + + </RelativeLayout> + + <!-- bottom: lock pattern, emergency dialer and forgot pattern button --> + <LinearLayout + android:layout_weight="1" + android:layout_width="match_parent" + android:layout_height="0dip" + android:orientation="vertical" + android:gravity="center"> + + <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern" + android:layout_width="354dip" + android:layout_height="354dip" + android:layout_marginTop="50dip"/> <!-- Emergency and forgot pattern buttons. --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:gravity="center_horizontal"> + style="?android:attr/buttonBarStyle" + android:gravity="center" + android:weightSum="2"> <Button android:id="@+id/forgotPatternButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - style="@style/Widget.Button.Transparent" - android:drawableLeft="@drawable/ic_emergency" + style="?android:attr/buttonBarButtonStyle" + android:drawableLeft="@drawable/lockscreen_forgot_password_button" android:drawablePadding="8dip" android:text="@string/lockscreen_forgot_pattern_button_text" android:visibility="gone" @@ -58,7 +98,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - style="@style/Widget.Button.Transparent" + style="?android:attr/buttonBarButtonStyle" android:drawableLeft="@drawable/ic_emergency" android:drawablePadding="8dip" android:text="@string/lockscreen_emergency_call" @@ -69,19 +109,5 @@ </LinearLayout> - <!-- right side: lock pattern --> - <LinearLayout - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="0dip" - android:gravity="center" - > - <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern" - android:layout_width="354dip" - android:layout_height="354dip" - android:layout_marginTop="50dip" - /> - </LinearLayout> - </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient> diff --git a/core/res/res/layout-sw600dp/keyguard_transport_control.xml b/core/res/res/layout-sw600dp/keyguard_transport_control.xml new file mode 100644 index 000000000000..86b103edd5b2 --- /dev/null +++ b/core/res/res/layout-sw600dp/keyguard_transport_control.xml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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. +--> + +<!-- *** Note *** This should mirror the file in layout/ with the exception of the background set + here for adding a drop shadow on tablets. --> + +<com.android.internal.widget.TransportControlView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transport_controls" + android:background="@drawable/transportcontrol_bg"> + + <!-- FrameLayout used as scrim to show between album art and buttons --> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:foreground="@drawable/ic_lockscreen_player_background"> + <!-- We use ImageView for its cropping features, otherwise could be android:background --> + <ImageView + android:id="@+id/albumart" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="fill" + android:scaleType="centerCrop" + android:adjustViewBounds="false" + /> + </FrameLayout> + + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom"> + <TextView + android:id="@+id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dip" + android:layout_marginLeft="16dip" + android:layout_marginRight="16dip" + android:gravity="center_horizontal" + android:singleLine="true" + android:ellipsize="end" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="5dip"> + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1"> + <ImageView + android:id="@+id/btn_prev" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:src="@drawable/ic_media_previous" + android:clickable="true" + android:background="?android:attr/selectableItemBackground" + android:padding="10dip" + android:contentDescription="@string/lockscreen_transport_prev_description"/> + </FrameLayout> + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1"> + <ImageView + android:id="@+id/btn_play" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:clickable="true" + android:src="@drawable/ic_media_play" + android:background="?android:attr/selectableItemBackground" + android:padding="10dip" + android:contentDescription="@string/lockscreen_transport_play_description"/> + </FrameLayout> + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1"> + <ImageView + android:id="@+id/btn_next" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:clickable="true" + android:src="@drawable/ic_media_next" + android:background="?android:attr/selectableItemBackground" + android:padding="10dip" + android:contentDescription="@string/lockscreen_transport_next_description"/> + </FrameLayout> + </LinearLayout> + </LinearLayout> + +</com.android.internal.widget.TransportControlView> diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml index 2392618c539b..b0f1bc5e680b 100644 --- a/core/res/res/layout/screen_action_bar.xml +++ b/core/res/res/layout/screen_action_bar.xml @@ -19,6 +19,8 @@ This is an optimized layout for a screen with the Action Bar enabled. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" android:orientation="vertical" android:fitsSystemWindows="true"> <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container" diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml index 19b861c9d955..2a8c7c381857 100644 --- a/core/res/res/layout/screen_action_bar_overlay.xml +++ b/core/res/res/layout/screen_action_bar_overlay.xml @@ -19,38 +19,45 @@ This is an optimized layout for a screen with the Action Bar enabled overlaying application content. --> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" android:fitsSystemWindows="true"> <FrameLayout android:id="@android:id/content" android:layout_width="match_parent" android:layout_height="match_parent" /> - <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="?android:attr/actionBarStyle" - android:gravity="top"> - <com.android.internal.widget.ActionBarView - android:id="@+id/action_bar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="?android:attr/actionBarStyle" /> - <com.android.internal.widget.ActionBarContextView - android:id="@+id/action_context_bar" + <LinearLayout android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="top"> + <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:visibility="gone" - style="?android:attr/actionModeStyle" /> - </com.android.internal.widget.ActionBarContainer> - <ImageView android:src="?android:attr/windowContentOverlay" - android:scaleType="fitXY" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@id/action_bar_container" /> + android:layout_alignParentTop="true" + style="?android:attr/actionBarStyle" + android:gravity="top"> + <com.android.internal.widget.ActionBarView + android:id="@+id/action_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + style="?android:attr/actionBarStyle" /> + <com.android.internal.widget.ActionBarContextView + android:id="@+id/action_context_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" + style="?android:attr/actionModeStyle" /> + </com.android.internal.widget.ActionBarContainer> + <ImageView android:src="?android:attr/windowContentOverlay" + android:scaleType="fitXY" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/action_bar_container" /> + </LinearLayout> <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignParentBottom="true" + android:layout_gravity="bottom" style="?android:attr/actionBarSplitStyle" android:visibility="gone" android:gravity="center"/> -</RelativeLayout> +</FrameLayout> diff --git a/core/res/res/layout/screen_simple.xml b/core/res/res/layout/screen_simple.xml index 87c29f6ebf03..c1914e7964b9 100644 --- a/core/res/res/layout/screen_simple.xml +++ b/core/res/res/layout/screen_simple.xml @@ -22,6 +22,8 @@ enabled. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical"> <ViewStub android:id="@+id/action_mode_bar_stub" diff --git a/core/res/res/layout/screen_simple_overlay_action_mode.xml b/core/res/res/layout/screen_simple_overlay_action_mode.xml index eb093e787beb..c790d10c529e 100644 --- a/core/res/res/layout/screen_simple_overlay_action_mode.xml +++ b/core/res/res/layout/screen_simple_overlay_action_mode.xml @@ -21,6 +21,8 @@ enabled. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" android:fitsSystemWindows="true"> <FrameLayout android:id="@android:id/content" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 4eb47cdf4cfd..c488116dd9e4 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -171,7 +171,7 @@ <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Kry toegang tot beskikbare rekeninge."</string> <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardewarekontroles"</string> <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Direkte toegang tot hardeware op die selfoon."</string> - <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"foonoproepe"</string> + <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Foonoproepe"</string> <string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"Monitor, neem op, en verwerk foonoproepe."</string> <string name="permgrouplab_systemTools" msgid="4652191644082714048">"Stelselhulpmiddels"</string> <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Laervlak-toegang en -beheer van die stelsel."</string> @@ -991,8 +991,8 @@ <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Kon nie jou SD-kaart vir USB-massaberging gebruik nie."</string> <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB gekoppel"</string> <string name="usb_storage_notification_message" msgid="7380082404288219341">"Kies om lêers na/van jou rekenaar te kopieer."</string> - <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Skakel USB-geheue af"</string> - <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Kies om USB-geheue af te skakel."</string> + <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Skakel USB-berging af"</string> + <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Kies om USB-berging af te skakel."</string> <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-berging in gebruik"</string> <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Voordat jy USB-berging afskakel, maak seker dat jy jou Android se USB-berging van jou rekenaar ontheg (\"uitgestoot\") het."</string> <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Voordat jy die USB-berging afskakel, maak seker dat jy jou Android se SD-kaart uit die rekenaar ontheg (uitgeskiet) het."</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 97ad227d183a..27d0be39fa63 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -159,7 +159,7 @@ <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjenester, der koster dig penge"</string> <string name="permgroupdesc_costMoney" msgid="8193824940620517189">"Tillader, at en applikation kan gøre ting, som kan koste penge."</string> <string name="permgrouplab_messages" msgid="7521249148445456662">"Dine beskeder"</string> - <string name="permgroupdesc_messages" msgid="7045736972019211994">"Læs og skriv dine sms-, e-mail- og andre beskeder."</string> + <string name="permgroupdesc_messages" msgid="7045736972019211994">"Læs og skriv dine sms-, e-mail og andre beskeder."</string> <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Dine personlige oplysninger"</string> <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Få direkte adgang til dine kontakter og din kalender, der er gemt på tabletcomputeren."</string> <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Få direkte adgang til dine kontakter og din kalender, der er gemt på telefonen."</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index a5caabfcbd4e..aa3849320c5e 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1024,7 +1024,7 @@ <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Verificando errores"</string> <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Almacenamiento USB en blanco"</string> <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tarjeta SD vacía"</string> - <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Almacenamiento USB en blanco o sistema de archivos no compatible."</string> + <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Almacenamiento USB vacío o sistema de archivos no compatible"</string> <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Tarjeta SD en blanco o el sistema de archivos no es compatible."</string> <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Almacenamiento USB dañado"</string> <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Tarjeta SD dañada"</string> @@ -1032,7 +1032,7 @@ <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Tarjeta SD dañada. Es posible que debas reformatearla."</string> <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Almacenamiento USB extraído inesperadamente"</string> <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Almacenamiento USB extraído de forma imprevista"</string> - <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desmontar el almacenamiento USB antes de extraerlo para evitar la pérdida de datos."</string> + <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desactivar el almacenamiento USB antes de extraerlo para evitar la pérdida de datos."</string> <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Es seguro extraer el almacenamiento USB"</string> <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Es seguro extraer la tarjeta SD"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 250415c0466f..fd248e570c78 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -137,7 +137,7 @@ <string name="turn_off_radio" msgid="8198784949987062346">"כבה אלחוטי"</string> <string name="screen_lock" msgid="799094655496098153">"נעילת מסך"</string> <string name="power_off" msgid="4266614107412865048">"כיבוי"</string> - <string name="shutdown_progress" msgid="2281079257329981203">"מבצע כיבוי..."</string> + <string name="shutdown_progress" msgid="2281079257329981203">"מכבה..."</string> <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"הטבלט שלך יכבה."</string> <string name="shutdown_confirm" product="default" msgid="649792175242821353">"הטלפון שלך יכובה."</string> <string name="shutdown_confirm_question" msgid="6656441286856415014">"האם ברצונך לבצע כיבוי?"</string> @@ -740,7 +740,7 @@ <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"כתוב את ההיסטוריה והסימניות של הדפדפן"</string> <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"מאפשר ליישום לשנות את ההיסטוריה או את הסימניות של הדפדפן המאוחסנות בטבלט. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את הנתונים בדפדפן."</string> <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"מאפשר ליישום לשנות את ההיסטוריה או הסימניות של הדפדפן המאוחסנות בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני הדפדפן."</string> - <string name="permlab_setAlarm" msgid="5924401328803615165">"הגדר התראה בשעון המעורר"</string> + <string name="permlab_setAlarm" msgid="5924401328803615165">"הגדר צלצול בשעון המעורר"</string> <string name="permdesc_setAlarm" msgid="5966966598149875082">"מאפשר ליישום להגדיר התראה ביישום מותקן של שעון מעורר. ייתכן שיישומי שעון מעורר מסוימים לא יישמו תכונה זו."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"הוסף דואר קולי"</string> <string name="permdesc_addVoicemail" msgid="4828507394878206682">"מאפשר ליישום להוסיף הודעות לתיבת הדואר הנכנס של הדואר הקולי."</string> @@ -895,8 +895,8 @@ <string name="chooseUsbActivity" msgid="7892597146032121735">"בחר יישום עבור מכשיר ה-USB"</string> <string name="noApplications" msgid="1691104391758345586">"אין יישומים שיכולים לבצע פעולה זו."</string> <string name="aerr_title" msgid="1905800560317137752"></string> - <string name="aerr_application" msgid="932628488013092776">"למרבה הצער, <xliff:g id="APPLICATION">%1$s</xliff:g> הפסיק לפעול."</string> - <string name="aerr_process" msgid="4507058997035697579">"למרבה הצער, התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הופסק."</string> + <string name="aerr_application" msgid="932628488013092776">"לצערנו ה<xliff:g id="APPLICATION">%1$s</xliff:g> הפסיק לפעול."</string> + <string name="aerr_process" msgid="4507058997035697579">"לצערנו, התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הופסק."</string> <string name="anr_title" msgid="4351948481459135709"></string> <string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g> אינו מגיב."\n\n" האם ברצונך לסגור אותו?"</string> <string name="anr_activity_process" msgid="7018289416670457797">"פעילות <xliff:g id="ACTIVITY">%1$s</xliff:g> אינה מגיבה."\n\n"האם ברצונך לסגור אותה?"</string> @@ -940,8 +940,8 @@ <string name="volume_icon_description_incall" msgid="8890073218154543397">"עוצמת קול של שיחות"</string> <string name="volume_icon_description_media" msgid="4217311719665194215">"עוצמת קול של מדיה"</string> <string name="volume_icon_description_notification" msgid="7044986546477282274">"עוצמת קול של התראות"</string> - <string name="ringtone_default" msgid="3789758980357696936">"רינגטון המוגדר כברירת מחדל"</string> - <string name="ringtone_default_with_actual" msgid="8129563480895990372">"רינגטון המוגדר כברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> + <string name="ringtone_default" msgid="3789758980357696936">"רינגטון ברירת מחדל"</string> + <string name="ringtone_default_with_actual" msgid="8129563480895990372">"רינגטון ברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> <string name="ringtone_silent" msgid="4440324407807468713">"שקט"</string> <string name="ringtone_picker_title" msgid="3515143939175119094">"רינגטונים"</string> <string name="ringtone_unknown" msgid="5477919988701784788">"רינגטון לא ידוע"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 6aac5206809b..ee098d5771f4 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -223,7 +223,7 @@ <string name="permlab_forceStopPackages" msgid="1447830113260156236">"다른 애플리케이션 강제 종료"</string> <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"애플리케이션이 다른 애플리케이션을 강제로 종료할 수 있도록 합니다."</string> <string name="permlab_forceBack" msgid="1804196839880393631">"강제로 애플리케이션 닫기"</string> - <string name="permdesc_forceBack" msgid="6534109744159919013">"애플리케이션이 포그라운드에 있는 활동을 강제로 닫고 되돌아갈 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string> + <string name="permdesc_forceBack" msgid="6534109744159919013">"애플리케이션이 포그라운드에 있는 작업을 강제로 닫고 되돌아갈 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string> <string name="permlab_dump" msgid="1681799862438954752">"시스템 내부 상태 검색"</string> <string name="permdesc_dump" msgid="2198776174276275220">"애플리케이션이 시스템의 내부 상태를 검색할 수 있도록 합니다. 단, 악성 애플리케이션이 이 기능을 이용하여 일반적으로 필요하지 않은 다양한 개인정보와 보안정보를 검색할 수 있습니다."</string> <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"화면 콘텐츠 검색"</string> @@ -446,7 +446,7 @@ <string name="permdesc_useCredentials" msgid="7416570544619546974">"애플리케이션이 인증 토큰을 요청하도록 합니다."</string> <string name="permlab_accessNetworkState" msgid="6865575199464405769">"네트워크 상태 보기"</string> <string name="permdesc_accessNetworkState" msgid="558721128707712766">"애플리케이션이 모든 네트워크의 상태를 볼 수 있도록 합니다."</string> - <string name="permlab_createNetworkSockets" msgid="9121633680349549585">"인터넷에 최대한 액세스"</string> + <string name="permlab_createNetworkSockets" msgid="9121633680349549585">"인터넷 액세스"</string> <string name="permdesc_createNetworkSockets" msgid="4593339106921772192">"애플리케이션이 네트워크 소켓을 만들 수 있도록 합니다."</string> <string name="permlab_writeApnSettings" msgid="505660159675751896">"네트워크 설정 및 트래픽 차단/변경"</string> <string name="permdesc_writeApnSettings" msgid="2369786339323021771">"애플리케이션이 모든 네트워크 트래픽을 가로채고 검사하거나 네트워크 설정을 변경하도록 허용합니다. 예를 들어 프록시나 APN의 포트를 변경할 수 있습니다. 악성 애플리케이션이 사용자 모르게 네트워크 패킷을 모니터링하고 리디렉션하며 수정할 수도 있습니다."</string> @@ -899,7 +899,7 @@ <string name="aerr_process" msgid="4507058997035697579">"<xliff:g id="PROCESS">%1$s</xliff:g> 프로세스가 중지되었습니다."</string> <string name="anr_title" msgid="4351948481459135709"></string> <string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g>이(가) 응답하지 않습니다."\n\n"닫으시겠습니까?"</string> - <string name="anr_activity_process" msgid="7018289416670457797">"<xliff:g id="ACTIVITY">%1$s</xliff:g> 활동이 응답하지 않습니다."\n\n"닫으시겠습니까?"</string> + <string name="anr_activity_process" msgid="7018289416670457797">"<xliff:g id="ACTIVITY">%1$s</xliff:g>이(가) 응답하지 않습니다."\n\n"닫으시겠습니까?"</string> <string name="anr_application_process" msgid="7208175830253210526">"<xliff:g id="APPLICATION">%1$s</xliff:g>이(가) 응답하지 않습니다. 닫으시겠습니까?"</string> <string name="anr_process" msgid="306819947562555821">"<xliff:g id="PROCESS">%1$s</xliff:g> 프로세스가 응답하지 않습니다."\n\n"닫으시겠습니까?"</string> <string name="force_close" msgid="8346072094521265605">"확인"</string> @@ -1208,7 +1208,7 @@ <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 지문:"</string> <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 지문:"</string> <string name="activity_chooser_view_see_all" msgid="180268188117163072">"전체 보기..."</string> - <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"활동 선택"</string> + <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"작업 선택"</string> <string name="share_action_provider_share_with" msgid="1791316789651185229">"공유 대상..."</string> <string name="status_bar_device_locked" msgid="3092703448690669768">"기기가 잠겼습니다."</string> <string name="list_delimeter" msgid="3975117572185494152">", "</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index d66c2d446323..44f4d10e98f6 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -348,7 +348,7 @@ <string name="permlab_accessFineLocation" msgid="8116127007541369477">"точное местоположение (GPS)"</string> <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Получать доступ к источникам точного местоположения, таким как GPS, когда это возможно. Вредоносные приложения могут использовать это разрешение для определения вашего местоположения и расходовать ресурс батареи."</string> <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Получать доступ к источникам точного местоположения, таким как GPS, если возможно. Вредоносные приложения могут использовать это разрешение для определения вашего местоположения и расходовать ресурс батареи."</string> - <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"отслеживать местоположение по сигналам сети"</string> + <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"примерное местоположение по координатам сети"</string> <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Получать доступ к источникам данных о местоположении, таким как база данных сотовой сети, для определения приблизительного местоположения планшетного ПК, когда это возможно. Вредоносные приложения могут использовать это разрешение для определения вашего приблизительного местоположения."</string> <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Получать доступ к источникам данных о местоположении, таким как база данных сотовой сети, для определения приблизительного местоположения телефона, если возможно. Вредоносные приложения могут использовать эту возможность для определения вашего приблизительного местоположения."</string> <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"получать доступ к SurfaceFlinger"</string> diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml index 5b488c08e0ea..921bcf4d6e57 100644 --- a/core/res/res/values-sw600dp/dimens.xml +++ b/core/res/res/values-sw600dp/dimens.xml @@ -43,7 +43,7 @@ <dimen name="action_bar_subtitle_bottom_margin">9dip</dimen> <!-- Size of clock font in LockScreen. --> - <dimen name="keyguard_pattern_unlock_clock_font_size">98sp</dimen> + <dimen name="keyguard_pattern_unlock_clock_font_size">112sp</dimen> <!-- Size of lockscreen outerring on unsecure unlock LockScreen --> <dimen name="keyguard_lockscreen_outerring_diameter">364dp</dimen> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index e88de76c6234..05da503e84df 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -136,7 +136,7 @@ <string name="turn_on_radio" msgid="3912793092339962371">"Vula okungenantambo"</string> <string name="turn_off_radio" msgid="8198784949987062346">"Vala okungenantambo"</string> <string name="screen_lock" msgid="799094655496098153">"Ukuvala isikrini"</string> - <string name="power_off" msgid="4266614107412865048">"Amandla avaliwe"</string> + <string name="power_off" msgid="4266614107412865048">"Vala amandla"</string> <string name="shutdown_progress" msgid="2281079257329981203">"Ivala shaqa..."</string> <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ithebhulethi yakho izocima."</string> <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ifoni yakho izocima."</string> @@ -146,7 +146,7 @@ <string name="global_actions" product="tablet" msgid="408477140088053665">"Okukhethwa konke kwethebhulethi"</string> <string name="global_actions" product="default" msgid="2406416831541615258">"Okukhethwa kukho kwefoni"</string> <string name="global_action_lock" msgid="2844945191792119712">"Ukuvala isikrini"</string> - <string name="global_action_power_off" msgid="4471879440839879722">"Amandla avaliwe"</string> + <string name="global_action_power_off" msgid="4471879440839879722">"Vala amandla"</string> <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Imodi ethulile"</string> <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Umsindo UVALIWE"</string> <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Umsindo UVULIWE"</string> @@ -838,7 +838,7 @@ <item quantity="one" msgid="2178576254385739855">"Kusasa"</item> <item quantity="other" msgid="2973062968038355991">"ezinsukwini ezing-<xliff:g id="COUNT">%d</xliff:g>"</item> </plurals> - <string name="preposition_for_date" msgid="9093949757757445117">"Ngomhla ka <xliff:g id="DATE">%s</xliff:g>"</string> + <string name="preposition_for_date" msgid="9093949757757445117">"ngo-<xliff:g id="DATE">%s</xliff:g>"</string> <string name="preposition_for_time" msgid="5506831244263083793">"e-<xliff:g id="TIME">%s</xliff:g>"</string> <string name="preposition_for_year" msgid="5040395640711867177">"phakathi- <xliff:g id="YEAR">%s</xliff:g>"</string> <string name="day" msgid="8144195776058119424">"usuku"</string> @@ -886,7 +886,7 @@ <string name="no" msgid="5141531044935541497">"Khansela"</string> <string name="dialog_alert_title" msgid="2049658708609043103">"Ukunaka"</string> <string name="loading" msgid="1760724998928255250">"Iyalayisha..."</string> - <string name="capital_on" msgid="1544682755514494298">"Ngomhla ka"</string> + <string name="capital_on" msgid="1544682755514494298">"VULIWE"</string> <string name="capital_off" msgid="6815870386972805832">"VALIWE"</string> <string name="whichApplication" msgid="4533185947064773386">"Qedela isenzo usebenzisa"</string> <string name="alwaysUse" msgid="4583018368000610438">"Sebenzisa ngokuzenzakalelayo kulesenzo."</string> @@ -1146,7 +1146,7 @@ <string name="checkbox_not_checked" msgid="5174639551134444056">"akuhloliwe"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"Okukhethiwe"</string> <string name="radiobutton_not_selected" msgid="2908760184307722393">"akukhethiwe"</string> - <string name="switch_on" msgid="551417728476977311">"Ngomhla ka-"</string> + <string name="switch_on" msgid="551417728476977311">"vuliwe"</string> <string name="switch_off" msgid="7249798614327155088">"valiwe"</string> <string name="togglebutton_pressed" msgid="4180411746647422233">"kucindezelwe."</string> <string name="togglebutton_not_pressed" msgid="4495147725636134425">"akucindezelwe."</string> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 9b8be854e325..c8ba26a336a7 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <!-- /* //device/apps/common/assets/res/any/strings.xml ** @@ -3365,4 +3365,13 @@ <!-- Delimeter used between each item in a textual list; for example "Alpha, Beta". [CHAR LIMIT=3] --> <string name="list_delimeter">", "</string> + <!-- STK sending DTMF, SMS, USSD, SS --> + <string name="sending">Sending...</string> + + <!-- STK launch Browser --> + <string name="launchBrowserDefault">Launch Browser?</string> + + <!-- STK setup Call --> + <string name="SetupCallDefault">Accept Call?</string> + </resources> diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java index 0cc883fe56ea..a781472a9af7 100644 --- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java +++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java @@ -90,7 +90,26 @@ public class BandwidthTest extends InstrumentationTestCase { */ @LargeTest public void testWifiDownload() throws Exception { - assertTrue(setDeviceWifiAndAirplaneMode(mSsid)); + assertTrue("Could not connect to wifi!", setDeviceWifiAndAirplaneMode(mSsid)); + downloadFile(); + } + + /** + * Ensure that downloading on mobile reports reasonable stats. + */ + @LargeTest + public void testMobileDownload() throws Exception { + // As part of the setup we disconnected from wifi; make sure we are connected to mobile and + // that we have data. + assertTrue("Do not have mobile data!", hasMobileData()); + downloadFile(); + } + + /** + * Helper method that downloads a file using http connection from a test server and reports the + * data usage stats to instrumentation out. + */ + protected void downloadFile() throws Exception { NetworkStats pre_test_stats = fetchDataFromProc(mUid); String ts = Long.toString(System.currentTimeMillis()); @@ -120,11 +139,28 @@ public class BandwidthTest extends InstrumentationTestCase { } /** - * Ensure that downloading on wifi reports reasonable stats. + * Ensure that uploading on wifi reports reasonable stats. */ @LargeTest public void testWifiUpload() throws Exception { assertTrue(setDeviceWifiAndAirplaneMode(mSsid)); + uploadFile(); + } + + /** + * Ensure that uploading on wifi reports reasonable stats. + */ + @LargeTest + public void testMobileUpload() throws Exception { + assertTrue(hasMobileData()); + uploadFile(); + } + + /** + * Helper method that downloads a test file to upload. The stats reported to instrumentation out + * only include upload stats. + */ + protected void uploadFile() throws Exception { // Download a file from the server. String ts = Long.toString(System.currentTimeMillis()); String targetUrl = BandwidthTestUtil.buildDownloadUrl( @@ -156,12 +192,30 @@ public class BandwidthTest extends InstrumentationTestCase { } /** - * We want to make sure that if we use the Download Manager to download stuff, + * We want to make sure that if we use wifi and the Download Manager to download stuff, * accounting still goes to the app making the call and that the numbers still make sense. */ @LargeTest public void testWifiDownloadWithDownloadManager() throws Exception { assertTrue(setDeviceWifiAndAirplaneMode(mSsid)); + downloadFileUsingDownloadManager(); + } + + /** + * We want to make sure that if we use mobile data and the Download Manager to download stuff, + * accounting still goes to the app making the call and that the numbers still make sense. + */ + @LargeTest + public void testMobileDownloadWithDownloadManager() throws Exception { + assertTrue(hasMobileData()); + downloadFileUsingDownloadManager(); + } + + /** + * Helper method that downloads a file from a test server using the download manager and reports + * the stats to instrumentation out. + */ + protected void downloadFileUsingDownloadManager() throws Exception { // If we are using the download manager, then the data that is written to /proc/uid_stat/ // is accounted against download manager's uid, since it uses pre-ICS API. int downloadManagerUid = mConnectionUtil.downloadManagerUid(); @@ -195,6 +249,7 @@ public class BandwidthTest extends InstrumentationTestCase { /** * Fetch network data from /proc/uid_stat/uid + * * @return populated {@link NetworkStats} */ public NetworkStats fetchDataFromProc(int uid) { @@ -210,7 +265,8 @@ public class BandwidthTest extends InstrumentationTestCase { } /** - * Turn on Airplane mode and connect to the wifi + * Turn on Airplane mode and connect to the wifi. + * * @param ssid of the wifi to connect to * @return true if we successfully connected to a given network. */ @@ -219,12 +275,25 @@ public class BandwidthTest extends InstrumentationTestCase { assertTrue(mConnectionUtil.connectToWifi(ssid)); assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED, ConnectionUtil.LONG_TIMEOUT)); - return mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, - ConnectionUtil.LONG_TIMEOUT); + assertTrue(mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI, + State.CONNECTED, ConnectionUtil.LONG_TIMEOUT)); + return mConnectionUtil.hasData(); + } + + /** + * Helper method to make sure we are connected to mobile data. + * + * @return true if we successfully connect to mobile data. + */ + public boolean hasMobileData() { + assertTrue("Not connected to mobile", mConnectionUtil.isConnectedToMobile()); + assertFalse("Still connected to wifi.", mConnectionUtil.isConnectedToWifi()); + return mConnectionUtil.hasData(); } /** * Output the {@link NetworkStats} to Instrumentation out. + * * @param label to attach to this given stats. * @param stats {@link NetworkStats} to add. * @param results {@link Bundle} to be added to. @@ -281,4 +350,4 @@ public class BandwidthTest extends InstrumentationTestCase { } return true; } -}
\ No newline at end of file +} diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java index d663aad47b9e..a5e5ab0e77b9 100644 --- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java +++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java @@ -44,6 +44,8 @@ import com.android.bandwidthtest.NetworkState; import com.android.bandwidthtest.NetworkState.StateTransitionDirection; import com.android.internal.util.AsyncChannel; +import java.io.IOException; +import java.net.UnknownHostException; import java.util.List; /* @@ -257,14 +259,14 @@ public class ConnectionUtil { mConnectivityState[networkType].recordState(networkState); } - /** - * Set the state transition criteria - * - * @param networkType - * @param initState - * @param transitionDir - * @param targetState - */ + /** + * Set the state transition criteria + * + * @param networkType + * @param initState + * @param transitionDir + * @param targetState + */ public void setStateTransitionCriteria(int networkType, State initState, StateTransitionDirection transitionDir, State targetState) { mConnectivityState[networkType].setStateTransitionCriteria( @@ -495,7 +497,8 @@ public class ConnectionUtil { * @return true if connected to a mobile network, false otherwise. */ public boolean isConnectedToMobile() { - return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE); + NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); + return networkInfo.isConnected(); } /** @@ -503,10 +506,10 @@ public class ConnectionUtil { * @return true if connected to wifi, false otherwise. */ public boolean isConnectedToWifi() { - return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI); + NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + return networkInfo.isConnected(); } - /** * Associate the device to given SSID * If the device is already associated with a WiFi, disconnect and forget it, @@ -681,4 +684,30 @@ public class ConnectionUtil { } Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode())); } + + /** + * Helper method used to test data connectivity by pinging a series of popular sites. + * @return true if device has data connectivity, false otherwise. + */ + public boolean hasData() { + String[] hostList = {"www.google.com", "www.yahoo.com", + "www.bing.com", "www.facebook.com", "www.ask.com"}; + try { + for (int i = 0; i < hostList.length; ++i) { + String host = hostList[i]; + Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host); + int status = p.waitFor(); + if (status == 0) { + return true; + } + } + } catch (UnknownHostException e) { + Log.e(LOG_TAG, "Ping test Failed: Unknown Host"); + } catch (IOException e) { + Log.e(LOG_TAG, "Ping test Failed: IOException"); + } catch (InterruptedException e) { + Log.e(LOG_TAG, "Ping test Failed: InterruptedException"); + } + return false; + } }
\ No newline at end of file diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java index e1db073c0713..1df763a48540 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java @@ -256,6 +256,10 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L); assertEquals(24, stats.size()); + // try removing invalid data; should be no change + stats.removeBucketsBefore(0 - DAY_IN_MILLIS); + assertEquals(24, stats.size()); + // try removing far before buckets; should be no change stats.removeBucketsBefore(TEST_START - YEAR_IN_MILLIS); assertEquals(24, stats.size()); diff --git a/docs/html/guide/developing/building/building-cmdline.jd b/docs/html/guide/developing/building/building-cmdline.jd index d78a4f55c069..c43962a81a28 100644 --- a/docs/html/guide/developing/building/building-cmdline.jd +++ b/docs/html/guide/developing/building/building-cmdline.jd @@ -365,7 +365,7 @@ test project, the tested project is also cleaned.</dd> <dd>Builds a test project and the tested project, installs both <code>.apk</code> files, and runs the tests.</dd> - <dt><code>ant emma debug installt test</code></dt> + <dt><code>ant emma debug install test</code></dt> <dd>Builds a test project and the tested project, installs both <code>.apk</code> files, and runs the tests with code coverage enabled.</dd> diff --git a/docs/html/guide/topics/resources/drawable-resource.jd b/docs/html/guide/topics/resources/drawable-resource.jd index fdf6c5add1fb..80de9f951081 100644 --- a/docs/html/guide/topics/resources/drawable-resource.jd +++ b/docs/html/guide/topics/resources/drawable-resource.jd @@ -646,6 +646,7 @@ In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code> android:state_checkable=["true" | "false"] android:state_checked=["true" | "false"] android:state_enabled=["true" | "false"] + android:state_activated=["true" | "false"] android:state_window_focused=["true" | "false"] /> </selector> </pre> @@ -690,8 +691,8 @@ child of a <code><selector></code> element. <dd><em>Boolean</em>. "true" if this item should be used when the object is pressed (such as when a button is touched/clicked); "false" if this item should be used in the default, non-pressed state.</dd> <dt><code>android:state_focused</code></dt> - <dd><em>Boolean</em>. "true" if this item should be used when the object is focused (such as when a button -is highlighted using the trackball/d-pad); "false" if this item should be used in the default, + <dd><em>Boolean</em>. "true" if this item should be used when the object has input focus +(such as when the user selects a text input); "false" if this item should be used in the default, non-focused state.</dd> <dt><code>android:state_hovered</code></dt> <dd><em>Boolean</em>. "true" if this item should be used when the object is being hovered @@ -699,8 +700,11 @@ by a cursor; "false" if this item should be used in the default, non-hovered sta drawable may be the same drawable used for the "focused" state. <p>Introduced in API level 14.</p></dd> <dt><code>android:state_selected</code></dt> - <dd><em>Boolean</em>. "true" if this item should be used when the object is selected (such as when a -tab is opened); "false" if this item should be used when the object is not selected.</dd> + <dd><em>Boolean</em>. "true" if this item should be used when the object is the current +user selection when navigating with a directional control (such as when navigating through a list +with a d-pad); "false" if this item should be used when the object is not selected. +<p>The selected state is used when focus (<code>android:state_focused</code>) is not sufficient +(such as when list view has focus and an item within it is selected with a d-pad).</p></dd> <dt><code>android:state_checkable</code></dt> <dd><em>Boolean</em>. "true" if this item should be used when the object is checkable; "false" if this item should be used when the object is not checkable. (Only useful if the object can @@ -709,8 +713,14 @@ transition between a checkable and non-checkable widget.)</dd> <dd><em>Boolean</em>. "true" if this item should be used when the object is checked; "false" if it should be used when the object is un-checked.</dd> <dt><code>android:state_enabled</code></dt> - <dd><em>Boolean</em>. "true" if this item should be used when the object is enabled (capable of -receiving touch/click events); "false" if it should be used when the object is disabled.</dd> + <dd><em>Boolean</em>. "true" if this item should be used when the object is enabled +(capable of receiving touch/click events); "false" if it should be used when the object is +disabled.</dd> + <dt><code>android:state_activated</code></dt> + <dd><em>Boolean</em>. "true" if this item should be used when the object is activated as +the persistent selection (such as to "highlight" the previously selected list item in a persistent +navigation view); "false" if it should be used when the object is not activated. +<p>Introduced in API level 11.</p></dd> <dt><code>android:state_window_focused</code></dt> <dd><em>Boolean</em>. "true" if this item should be used when the application window has focus (the application is in the foreground), "false" if this item should be used when the application diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd index f87e1f6be976..afbad57094d0 100644 --- a/docs/html/sdk/ndk/index.jd +++ b/docs/html/sdk/ndk/index.jd @@ -1,18 +1,19 @@ ndk=true -ndk.win_download=android-ndk-r6b-windows.zip -ndk.win_bytes=67670219 -ndk.win_checksum=f496b48fffb6d341303de170a081b812 +ndk.win_download=android-ndk-r7-windows.zip +ndk.win_bytes=81270552 +ndk.win_checksum=55483482cf2b75e8dd1a5d9a7caeb6e5 -ndk.mac_download=android-ndk-r6b-darwin-x86.tar.bz2 -ndk.mac_bytes=52798843 -ndk.mac_checksum=65f2589ac1b08aabe3183f9ed1a8ce8e +ndk.mac_download=android-ndk-r7-darwin-x86.tar.bz2 +ndk.mac_bytes=71262092 +ndk.mac_checksum=817ca5675a1dd44078098e43070f19b6 -ndk.linux_download=android-ndk-r6b-linux-x86.tar.bz2 -ndk.linux_bytes=46532436 -ndk.linux_checksum=309f35e49b64313cfb20ac428df4cec2 +ndk.linux_download=android-ndk-r7-linux-x86.tar.bz2 +ndk.linux_bytes=64884365 +ndk.linux_checksum=bf15e6b47bf50824c4b96849bf003ca3 page.title=Android NDK + @jd:body <h2 id="notes">Revisions</h2> @@ -61,6 +62,310 @@ padding: .25em 1em; <div class="toggleable open"> <a href="#" onclick="return toggleDiv(this)"><img src= "{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px"> + Android NDK, Revision 7</a> <em>(November 2011)</em> + + <div class="toggleme"> + <p>This release of the NDK includes new features to support the Android 4.0 platform as well + as many other additions and improvements:</p> + + <dl> + <dt>New features</dt> + + <dd> + <ul> + <li>Added official NDK APIs for Android 4.0 (API level 14), which adds the following + native features to the platform: + + <ul> + <li>Added native multimedia API based on the Khronos Group OpenMAX AL™ 1.0.1 + standard. The new <code><OMXAL/OpenMAXAL.h></code> and + <code><OMXAL/OpenMAXAL_Android.h></code> headers allow applications targeting + API level 14 to perform multimedia output directly from native code by using a new + Android-specific buffer queue interface. For more details, see + <code>docs/openmaxal/index.html</code> and <a href= + "http://www.khronos.org/openmax/">http://www.khronos.org/openmax/</a>.</li> + + <li>Updated the native audio API based on the Khronos Group OpenSL ES 1.0.1™ + standard. With API Level 14, you can now decode compressed audio (e.g. MP3, AAC, + Vorbis) to PCM. For more details, see <code>docs/opensles/index.html</code> and + <a href= + "http://www.khronos.org/opensles">http://www.khronos.org/opensles/</a>.</li> + </ul> + </li> + + <li>Added CCache support. To speed up large rebuilds, define the + <code>NDK_CCACHE</code> environment variable to <code>ccache</code> (or the path to + your <code>ccache</code> binary). When declared, the NDK build system automatically + uses CCache when compiling any source file. For example: + <pre> +export NDK_CCACHE=ccache +</pre> + <p class="note"><strong>Note:</strong> CCache is not included in the NDK release + so you must have it installed prior to using it. For more information about CCache, see + <a href="http://ccache.samba.org">http://ccache.samba.org</a>.</p> + </li> + + <li>Added support for setting <code>APP_ABI</code> to <code>all</code> to indicate that + you want to build your NDK modules for all the ABIs supported by your given NDK + release. This means that either one of the following two lines in your + <code>Application.mk</code> are equivalent with this release: + <pre> +APP_ABI := all +APP_ABI := armeabi armeabi-v7a x86 +</pre> + + <p>This also works if you define <code>APP_ABI</code> when calling + <code>ndk-build</code> from the command-line, which is a quick way to check that your + project builds for all supported ABIs without changing the project's + <code>Application.mk file</code>. For example:</p> + <pre> +ndk-build APP_ABI=all +</pre> + </li> + + <li>Added a <code>LOCAL_CPP_FEATURES</code> variable in <code>Android.mk</code> that + allows you to declare which C++ features (RTTI or Exceptions) your module uses. This + ensures that the final linking works correctly if you have prebuilt modules that depend + on these features. See <code>docs/ANDROID-MK.html</code> and + <code>docs/CPLUSPLUS-SUPPORT.html</code> for more details.</li> + + <li>Shortened paths to source and object files that are used in build commands. When + invoking <code>$NDK/ndk-build</code> from your project path, the paths to the source, + object, and binary files that are passed to the build commands are significantly + shorter now, because they are passed relative to the current directory. This is useful + when building projects with a lot of source files, to avoid limits on the maximum + command line length supported by your host operating system. The behavior is unchanged + if you invoke <code>ndk-build</code> from a sub-directory of your project tree, or if + you define <code>NDK_PROJECT_PATH</code> to point to a specific directory.</li> + </ul> + </dd> + + <dt>Experimental features</dt> + + <dd> + You can now build your NDK source files on Windows <em>without</em> Cygwin by calling the + <code>ndk-build.cmd</code> script from the command line from your project path. The + script takes exactly the same arguments as the original <code>ndk-build</code> script. + The Windows NDK package comes with its own prebuilt binaries for GNU Make, Awk and other + tools required by the build. You should not need to install anything else to get a + working build system. + + <p class="caution"><strong>Important:</strong> <code>ndk-gdb</code> does not work on + Windows, so you still need Cygwin to debug.</p> + + <p>This feature is still experimental, so feel free to try it and report issues on the + <a href="http://b.android.com">public bug database</a> or <a href= + "http://groups.google.com/group/android-ndk">public forum</a>. All samples and unit tests + shipped with the NDK succesfully compile with this feature.</p> + </dd> + + <dt>Important bug fixes</dt> + + <dd> + <ul> + <li>Imported shared libraries are now installed by default to the target installation + location (<code>libs/<abi></code>) if <code>APP_MODULES</code> is not defined in + your <code>Application.mk</code>. For example, if a top-level module <code>foo</code> + imports a module <code>bar</code>, then both <code>libfoo.so</code> and + <code>libbar.so</code> are copied to the install location. Previously, only + <code>libfoo.so</code> was copied, unless you listed <code>bar</code> in your + <code>APP_MODULES</code> too. If you define <code>APP_MODULES</code> explicitly, the + behavior is unchanged.</li> + + <li><code>ndk-gdb</code> now works correctly for activities with multiple categories in + their MAIN intent filters.</li> + + <li>Static library imports are now properly transitive. For example, if a top-level + module <code>foo</code> imports static library <code>bar</code> that imports static + library <code>zoo</code>, the <code>libfoo.so</code> will now be linked against both + <code>libbar.a</code> and <code>libzoo.a</code>.</li> + </ul> + </dd> + + <dt>Other changes</dt> + + <dd> + <ul> + <li><code>docs/NATIVE-ACTIVITY.HTML</code>: Fixed typo. The minimum API level should be + 9, not 8 for native activities.</li> + + <li><code>docs/STABLE-APIS.html</code>: Added missing documentation listing EGL as a + supported stable API, starting from API level 9.</li> + + <li><code>download-toolchain-sources.sh</code>: Updated to download the toolchain + sources from <a href="http://android.googlesource.com">android.googlesource.com</a>, + which is the new location for the AOSP servers.</li> + + <li>Added a new C++ support runtime named <code>gabi++</code>. More details about it + are available in the updated <code>docs/CPLUSPLUS-SUPPORT.html</code>.</li> + + <li>Added a new C++ support runtime named <code>gnustl_shared</code> that corresponds + to the shared library version of GNU libstdc++ v3 (GPLv3 license). See more info at + <code>docs/CPLUSPLUS-SUPPORT.html</code></li> + + <li>Added support for RTTI in the STLport C++ runtimes (no support for + exceptions).</li> + + <li>Added support for multiple file extensions in <code>LOCAL_CPP_EXTENSION</code>. For + example, to compile both <code>foo.cpp</code> and <code>bar.cxx</code> as C++ sources, + declare the following: + <pre> +LOCAL_CPP_EXTENSION := .cpp .cxx +</pre> + </li> + + <li>Removed many unwanted exported symbols from the link-time shared system libraries + provided by the NDK. This ensures that code generated with the standalone toolchain + doesn't risk to accidentally depend on a non-stable ABI symbol (e.g. any libgcc.a + symbol that changes each time the toolchain used to build the platform is changed)</li> + + <li>Refreshed the EGL and OpenGLES Khronos headers to support more extensions. Note + that this does <em>not</em> change the NDK ABIs for the corresponding libraries, + because each extension must be probed at runtime by the client application. + + <p>The extensions that are available depend on your actual device and GPU drivers, + not the platform version the device runs on. The header changes simply add new + constants and types to make it easier to use the extensions when they have been + probed with <code>eglGetProcAddress()</code> or <code>glGetProcAddress()</code>. The + following list describes the newly supported extensions:</p> + + <dl> + <dt>GLES 1.x</dt> + + <dd> + <ul> + <li><code>GL_OES_vertex_array_object</code></li> + + <li><code>GL_OES_EGL_image_external</code></li> + + <li><code>GL_APPLE_texture_2D_limited_npot</code></li> + + <li><code>GL_EXT_blend_minmax</code></li> + + <li><code>GL_EXT_discard_framebuffer</code></li> + + <li><code>GL_EXT_multi_draw_arrays</code></li> + + <li><code>GL_EXT_read_format_bgra</code></li> + + <li><code>GL_EXT_texture_filter_anisotropic</code></li> + + <li><code>GL_EXT_texture_format_BGRA8888</code></li> + + <li><code>GL_EXT_texture_lod_bias</code></li> + + <li><code>GL_IMG_read_format</code></li> + + <li><code>GL_IMG_texture_compression_pvrtc</code></li> + + <li><code>GL_IMG_texture_env_enhanced_fixed_function</code></li> + + <li><code>GL_IMG_user_clip_plane</code></li> + + <li><code>GL_IMG_multisampled_render_to_texture</code></li> + + <li><code>GL_NV_fence</code></li> + + <li><code>GL_QCOM_driver_control</code></li> + + <li><code>GL_QCOM_extended_get</code></li> + + <li><code>GL_QCOM_extended_get2</code></li> + + <li><code>GL_QCOM_perfmon_global_mode</code></li> + + <li><code>GL_QCOM_writeonly_rendering</code></li> + + <li><code>GL_QCOM_tiled_rendering</code></li> + </ul> + </dd> + + <dt>GLES 2.0</dt> + + <dd> + <ul> + <li><code>GL_OES_element_index_uint</code></li> + + <li><code>GL_OES_get_program_binary</code></li> + + <li><code>GL_OES_mapbuffer</code></li> + + <li><code>GL_OES_packed_depth_stencil</code></li> + + <li><code>GL_OES_texture_3D</code></li> + + <li><code>GL_OES_texture_float</code></li> + + <li><code>GL_OES_texture_float_linear</code></li> + + <li><code>GL_OES_texture_half_float_linear</code></li> + + <li><code>GL_OES_texture_npot</code></li> + + <li><code>GL_OES_vertex_array_object</code></li> + + <li><code>GL_OES_EGL_image_external</code></li> + + <li><code>GL_AMD_program_binary_Z400</code></li> + + <li><code>GL_EXT_blend_minmax</code></li> + + <li><code>GL_EXT_discard_framebuffer</code></li> + + <li><code>GL_EXT_multi_draw_arrays</code></li> + + <li><code>GL_EXT_read_format_bgra</code></li> + + <li><code>GL_EXT_texture_format_BGRA8888</code></li> + + <li><code>GL_EXT_texture_compression_dxt1</code></li> + + <li><code>GL_IMG_program_binary</code></li> + + <li><code>GL_IMG_read_format</code></li> + + <li><code>GL_IMG_shader_binary</code></li> + + <li><code>GL_IMG_texture_compression_pvrtc</code></li> + + <li><code>GL_IMG_multisampled_render_to_texture</code></li> + + <li><code>GL_NV_coverage_sample</code></li> + + <li><code>GL_NV_depth_nonlinear</code></li> + + <li><code>GL_QCOM_extended_get</code></li> + + <li><code>GL_QCOM_extended_get2</code></li> + + <li><code>GL_QCOM_writeonly_rendering</code></li> + + <li><code>GL_QCOM_tiled_rendering</code></li> + </ul> + </dd> + + <dt>EGL</dt> + + <dd> + <ul> + <li><code>EGL_ANDROID_recordable</code></li> + + <li><code>EGL_NV_system_time</code></li> + </ul> + </dd> + </dl> + </li> + </ul> + </dd> + </dl> + </div> +</div> + + + +<div class="toggleable closed"> + <a href="#" onclick="return toggleDiv(this)"><img src= + "{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px"> Android NDK, Revision 6b</a> <em>(August 2011)</em> <div class="toggleme"> diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 9a18f7da57b1..afe6a6e094bd 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -192,7 +192,8 @@ class="new">new!</span> <span style="display:none" class="zh-TW"></span> </h2> <ul> - <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6b</a> + <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r7</a> + <span class="new">new!</span> </li> <li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li> </ul> diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 79acd552b583..380b3d86718f 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -604,10 +604,13 @@ public final class Bitmap implements Parcelable { } Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true); if (config == Config.ARGB_8888 && !hasAlpha) { - bm.eraseColor(0xff000000); + nativeErase(bm.mNativeBitmap, 0xff000000); nativeSetHasAlpha(bm.mNativeBitmap, hasAlpha); } else { - bm.eraseColor(0); + // No need to initialize it to zeroes; it is backed by a VM byte array + // which is by definition preinitialized to all zeroes. + // + //nativeErase(bm.mNativeBitmap, 0); } return bm; } diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index 29fab11603a4..0521e6985eb1 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -17,6 +17,7 @@ package android.graphics; import java.lang.ref.WeakReference; + import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -141,6 +142,12 @@ public class SurfaceTexture { * android.view.Surface#lockCanvas} is called. For OpenGL ES, the EGLSurface should be * destroyed (via eglDestroySurface), made not-current (via eglMakeCurrent), and then recreated * (via eglCreateWindowSurface) to ensure that the new default size has taken effect. + * + * The width and height parameters must be no greater than the minimum of + * GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see + * {@link javax.microedition.khronos.opengles.GL10#glGetIntegerv glGetIntegerv}). + * An error due to invalid dimensions might not be reported until + * updateTexImage() is called. */ public void setDefaultBufferSize(int width, int height) { nativeSetDefaultBufferSize(width, height); @@ -152,7 +159,10 @@ public class SurfaceTexture { * implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target. */ public void updateTexImage() { - nativeUpdateTexImage(); + int err = nativeUpdateTexImage(); + if (err != 0) { + throw new RuntimeException("Error during updateTexImage (see logs)"); + } } /** @@ -258,7 +268,7 @@ public class SurfaceTexture { private native void nativeGetTransformMatrix(float[] mtx); private native long nativeGetTimestamp(); private native void nativeSetDefaultBufferSize(int width, int height); - private native void nativeUpdateTexImage(); + private native int nativeUpdateTexImage(); private native int nativeGetQueuedCount(); private native void nativeRelease(); diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java index 199952c436b4..20eb93fc1d56 100644 --- a/graphics/java/android/renderscript/RSSurfaceView.java +++ b/graphics/java/android/renderscript/RSSurfaceView.java @@ -30,7 +30,7 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; /** - * The Surface View for a graphics renderscript (RenderScriptGL) to draw on. + * The Surface View for a graphics renderscript (RenderScriptGL) to draw on. */ public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mSurfaceHolder; @@ -77,7 +77,7 @@ public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback * This method is part of the SurfaceHolder.Callback interface, and is * not normally called or subclassed by clients of RSSurfaceView. */ - public void surfaceDestroyed(SurfaceHolder holder) { + public synchronized void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when we return if (mRS != null) { mRS.setSurface(null, 0, 0); @@ -88,7 +88,7 @@ public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback * This method is part of the SurfaceHolder.Callback interface, and is * not normally called or subclassed by clients of RSSurfaceView. */ - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + public synchronized void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (mRS != null) { mRS.setSurface(holder, w, h); } @@ -125,7 +125,7 @@ public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback return rs; } - public void destroyRenderScriptGL() { + public synchronized void destroyRenderScriptGL() { mRS.destroy(); mRS = null; } diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index e2d6179ef046..d7dd4d6cb41e 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -79,7 +79,11 @@ public: // pointed to by the buf argument and a status of OK is returned. If no // slot is available then a status of -EBUSY is returned and buf is // unmodified. - virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, + // The width and height parameters must be no greater than the minimum of + // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv). + // An error due to invalid dimensions might not be reported until + // updateTexImage() is called. + virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height, uint32_t format, uint32_t usage); // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a @@ -176,7 +180,11 @@ public: // requestBuffers when a with and height of zero is requested. // A call to setDefaultBufferSize() may trigger requestBuffers() to // be called from the client. - status_t setDefaultBufferSize(uint32_t w, uint32_t h); + // The width and height parameters must be no greater than the minimum of + // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv). + // An error due to invalid dimensions might not be reported until + // updateTexImage() is called. + status_t setDefaultBufferSize(uint32_t width, uint32_t height); // getCurrentBuffer returns the buffer associated with the current image. sp<GraphicBuffer> getCurrentBuffer() const; diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h index eab764807f77..250f26773726 100644 --- a/include/media/MediaProfiles.h +++ b/include/media/MediaProfiles.h @@ -48,15 +48,21 @@ enum camcorder_quality { }; /** - *Set CIF as default maximum import and export resolution of video editor. - *The maximum import and export resolutions are platform specific, - *which should be defined in media_profiles.xml. + * Set CIF as default maximum import and export resolution of video editor. + * The maximum import and export resolutions are platform specific, + * which should be defined in media_profiles.xml. + * Set default maximum prefetch YUV frames to 6, which means video editor can + * queue up to 6 YUV frames in the video encoder source. + * This value is used to limit the amount of memory used by video editor + * engine when the encoder consumes YUV frames at a lower speed + * than video editor engine produces. */ enum videoeditor_capability { VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH = 352, VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT = 288, VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH = 352, VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT = 288, + VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES = 6 }; enum video_decoder { @@ -138,6 +144,8 @@ public: * videoeditor.input.height.max - max input video frame height * videoeditor.output.width.max - max output video frame width * videoeditor.output.height.max - max output video frame height + * maxPrefetchYUVFrames - max prefetch YUV frames in video editor engine. This value is used + * to limit the memory consumption. */ int getVideoEditorCapParamByName(const char *name) const; @@ -357,11 +365,12 @@ private: }; struct VideoEditorCap { VideoEditorCap(int inFrameWidth, int inFrameHeight, - int outFrameWidth, int outFrameHeight) + int outFrameWidth, int outFrameHeight, int frames) : mMaxInputFrameWidth(inFrameWidth), mMaxInputFrameHeight(inFrameHeight), mMaxOutputFrameWidth(outFrameWidth), - mMaxOutputFrameHeight(outFrameHeight) {} + mMaxOutputFrameHeight(outFrameHeight), + mMaxPrefetchYUVFrames(frames) {} ~VideoEditorCap() {} @@ -369,6 +378,7 @@ private: int mMaxInputFrameHeight; int mMaxOutputFrameWidth; int mMaxOutputFrameHeight; + int mMaxPrefetchYUVFrames; }; int getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const; diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index 5daafd5581aa..93ebfb99ff6f 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -1520,4 +1520,36 @@ TEST_F(SurfaceTextureGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) { EXPECT_EQ(1, buffers[2]->getStrongCount()); } +TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) { + int texHeight = 16; + ANativeWindowBuffer* anb; + + GLint maxTextureSize; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + + // make sure it works with small textures + mST->setDefaultBufferSize(16, texHeight); + EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + EXPECT_EQ(16, anb->width); + EXPECT_EQ(texHeight, anb->height); + EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ(NO_ERROR, mST->updateTexImage()); + + // make sure it works with GL_MAX_TEXTURE_SIZE + mST->setDefaultBufferSize(maxTextureSize, texHeight); + EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + EXPECT_EQ(maxTextureSize, anb->width); + EXPECT_EQ(texHeight, anb->height); + EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb)); + EXPECT_EQ(NO_ERROR, mST->updateTexImage()); + + // make sure it fails with GL_MAX_TEXTURE_SIZE+1 + mST->setDefaultBufferSize(maxTextureSize+1, texHeight); + EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + EXPECT_EQ(maxTextureSize+1, anb->width); + EXPECT_EQ(texHeight, anb->height); + EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb)); + ASSERT_NE(NO_ERROR, mST->updateTexImage()); +} + } // namespace android diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index fe1560568743..a2b80c25c439 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -2693,11 +2693,22 @@ public class AudioService extends IAudioService.Stub { mCallingUid = uid; } - public void unlinkToDeath() { + private void unlinkToDeath() { if (mSourceRef != null && mHandler != null) { mSourceRef.unlinkToDeath(mHandler, 0); } } + + @Override + protected void finalize() throws Throwable { + try { + unlinkToDeath(); + } catch (java.util.NoSuchElementException e) { + Log.w(TAG, e + " thrown by unlinkToDeath() during finalize, ignoring"); + } finally { + super.finalize(); + } + } } private Stack<FocusStackEntry> mFocusStack = new Stack<FocusStackEntry>(); @@ -2732,8 +2743,7 @@ public class AudioService extends IAudioService.Stub { if (!mFocusStack.empty() && mFocusStack.peek().mClientId.equals(clientToRemove)) { //Log.i(TAG, " removeFocusStackEntry() removing top of stack"); - FocusStackEntry fse = mFocusStack.pop(); - fse.unlinkToDeath(); + mFocusStack.pop(); if (signal) { // notify the new top of the stack it gained focus notifyTopOfAudioFocusStack(); @@ -2752,7 +2762,6 @@ public class AudioService extends IAudioService.Stub { Log.i(TAG, " AudioFocus abandonAudioFocus(): removing entry for " + fse.mClientId); stackIterator.remove(); - fse.unlinkToDeath(); } } } @@ -2858,6 +2867,9 @@ public class AudioService extends IAudioService.Stub { // if focus is already owned by this client and the reason for acquiring the focus // hasn't changed, don't do anything if (mFocusStack.peek().mFocusChangeType == focusChangeHint) { + // unlink death handler so it can be gc'ed. + // linkToDeath() creates a JNI global reference preventing collection. + cb.unlinkToDeath(afdh, 0); return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; } // the reason for the audio focus request has changed: remove the current top of @@ -3050,6 +3062,7 @@ public class AudioService extends IAudioService.Stub { if ((mRcClientDeathHandler != null) && (mRcClientDeathHandler.mCb != null)) { try { mRcClientDeathHandler.mCb.unlinkToDeath(mRcClientDeathHandler, 0); + mRcClientDeathHandler = null; } catch (java.util.NoSuchElementException e) { // not much we can do here Log.e(TAG, "Encountered " + e + " in unlinkToRcClientDeath()"); @@ -3057,6 +3070,12 @@ public class AudioService extends IAudioService.Stub { } } } + + @Override + protected void finalize() throws Throwable { + unlinkToRcClientDeath();// unlink exception handled inside method + super.finalize(); + } } /** @@ -3103,6 +3122,7 @@ public class AudioService extends IAudioService.Stub { if (packageName.equalsIgnoreCase(rcse.mReceiverComponent.getPackageName())) { // a stack entry is from the package being removed, remove it from the stack stackIterator.remove(); + rcse.unlinkToRcClientDeath(); } } if (mRCStack.empty()) { @@ -3183,6 +3203,7 @@ public class AudioService extends IAudioService.Stub { RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next(); if(rcse.mMediaIntent.equals(pi)) { stackIterator.remove(); + rcse.unlinkToRcClientDeath(); break; } } @@ -3444,7 +3465,7 @@ public class AudioService extends IAudioService.Stub { rcse.mCallingPackageName = callingPackageName; rcse.mCallingUid = Binder.getCallingUid(); if (rcClient == null) { - rcse.mRcClientDeathHandler = null; + // here rcse.mRcClientDeathHandler is null; break; } @@ -3500,7 +3521,6 @@ public class AudioService extends IAudioService.Stub { rcse.unlinkToRcClientDeath(); // reset the client-related fields rcse.mRcClient = null; - rcse.mRcClientDeathHandler = null; rcse.mCallingPackageName = null; } } diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index b17f2972807f..11ecd1f98e4e 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -463,7 +463,6 @@ public class MediaMetadataRetriever * The location should be specified according to ISO-6709 standard, under * a mp4/3gp box "@xyz". Location with longitude of -90 degrees and latitude * of 180 degrees will be retrieved as "-90.0000+180.0000", for instance. - * @hide */ public static final int METADATA_KEY_LOCATION = 23; // Add more here... diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index ad55ff86441b..6096b721ea6e 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -404,11 +404,12 @@ MediaProfiles::createVideoEditorCap(const char **atts, MediaProfiles *profiles) CHECK(!strcmp("maxInputFrameWidth", atts[0]) && !strcmp("maxInputFrameHeight", atts[2]) && !strcmp("maxOutputFrameWidth", atts[4]) && - !strcmp("maxOutputFrameHeight", atts[6])); + !strcmp("maxOutputFrameHeight", atts[6]) && + !strcmp("maxPrefetchYUVFrames", atts[8])); MediaProfiles::VideoEditorCap *pVideoEditorCap = new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]), - atoi(atts[5]), atoi(atts[7])); + atoi(atts[5]), atoi(atts[7]), atoi(atts[9])); logVideoEditorCap(*pVideoEditorCap); profiles->mVideoEditorCap = pVideoEditorCap; @@ -850,7 +851,8 @@ MediaProfiles::createDefaultVideoEditorCap(MediaProfiles *profiles) VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH, VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT, VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH, - VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT); + VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT, + VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES); } /*static*/ void MediaProfiles::createDefaultExportVideoProfiles(MediaProfiles *profiles) @@ -1019,6 +1021,8 @@ int MediaProfiles::getVideoEditorCapParamByName(const char *name) const return mVideoEditorCap->mMaxOutputFrameWidth; if (!strcmp("videoeditor.output.height.max", name)) return mVideoEditorCap->mMaxOutputFrameHeight; + if (!strcmp("maxPrefetchYUVFrames", name)) + return mVideoEditorCap->mMaxPrefetchYUVFrames; LOGE("The given video editor param name %s is not found", name); return -1; diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index 0dd93becf3a5..794c60b6a9a8 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -792,7 +792,7 @@ struct MyHandler : public AHandler { } if (mNumAccessUnitsReceived == 0) { -#if 0 +#if 1 LOGI("stream ended? aborting."); (new AMessage('abor', id()))->post(); break; diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java index 99cbb860d029..9c87c2244477 100644 --- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java +++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java @@ -16,8 +16,9 @@ package com.android.nfc_extras; -import android.annotation.SdkConstant; -import android.annotation.SdkConstant.SdkConstantType; +import java.util.HashMap; + +import android.content.Context; import android.nfc.INfcAdapterExtras; import android.nfc.NfcAdapter; import android.os.RemoteException; @@ -58,16 +59,22 @@ public final class NfcAdapterExtras { // protected by NfcAdapterExtras.class, and final after first construction, // except for attemptDeadServiceRecovery() when NFC crashes - we accept a // best effort recovery - private static NfcAdapter sAdapter; private static INfcAdapterExtras sService; - private static NfcAdapterExtras sSingleton; - private static NfcExecutionEnvironment sEmbeddedEe; - private static CardEmulationRoute sRouteOff; - private static CardEmulationRoute sRouteOnWhenScreenOn; + private static final CardEmulationRoute ROUTE_OFF = + new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null); + + // contents protected by NfcAdapterExtras.class + private static final HashMap<NfcAdapter, NfcAdapterExtras> sNfcExtras = new HashMap(); + + private final NfcExecutionEnvironment mEmbeddedEe; + private final CardEmulationRoute mRouteOnWhenScreenOn; + + private final NfcAdapter mAdapter; + final String mPackageName; /** get service handles */ - private static void initService() { - final INfcAdapterExtras service = sAdapter.getNfcAdapterExtrasInterface(); + private static void initService(NfcAdapter adapter) { + final INfcAdapterExtras service = adapter.getNfcAdapterExtrasInterface(); if (service != null) { // Leave stale rather than receive a null value. sService = service; @@ -84,31 +91,32 @@ public final class NfcAdapterExtras { * @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter} */ public static NfcAdapterExtras get(NfcAdapter adapter) { - synchronized(NfcAdapterExtras.class) { - if (sSingleton == null) { - try { - sAdapter = adapter; - sSingleton = new NfcAdapterExtras(); - sEmbeddedEe = new NfcExecutionEnvironment(sSingleton); - sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null); - sRouteOnWhenScreenOn = new CardEmulationRoute( - CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe); - initService(); - } finally { - if (sService == null) { - sRouteOnWhenScreenOn = null; - sRouteOff = null; - sEmbeddedEe = null; - sSingleton = null; - sAdapter = null; - } - } + Context context = adapter.getContext(); + if (context == null) { + throw new UnsupportedOperationException( + "You must pass a context to your NfcAdapter to use the NFC extras APIs"); + } + + synchronized (NfcAdapterExtras.class) { + if (sService == null) { + initService(adapter); + } + NfcAdapterExtras extras = sNfcExtras.get(adapter); + if (extras == null) { + extras = new NfcAdapterExtras(adapter); + sNfcExtras.put(adapter, extras); } - return sSingleton; + return extras; } } - private NfcAdapterExtras() {} + private NfcAdapterExtras(NfcAdapter adapter) { + mAdapter = adapter; + mPackageName = adapter.getContext().getPackageName(); + mEmbeddedEe = new NfcExecutionEnvironment(this); + mRouteOnWhenScreenOn = new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, + mEmbeddedEe); + } /** * Immutable data class that describes a card emulation route. @@ -153,8 +161,8 @@ public final class NfcAdapterExtras { */ void attemptDeadServiceRecovery(Exception e) { Log.e(TAG, "NFC Adapter Extras dead - attempting to recover"); - sAdapter.attemptDeadServiceRecovery(e); - initService(); + mAdapter.attemptDeadServiceRecovery(e); + initService(mAdapter); } INfcAdapterExtras getService() { @@ -166,18 +174,16 @@ public final class NfcAdapterExtras { * * <p class="note"> * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. - * - * @return */ public CardEmulationRoute getCardEmulationRoute() { try { - int route = sService.getCardEmulationRoute(); + int route = sService.getCardEmulationRoute(mPackageName); return route == CardEmulationRoute.ROUTE_OFF ? - sRouteOff : - sRouteOnWhenScreenOn; + ROUTE_OFF : + mRouteOnWhenScreenOn; } catch (RemoteException e) { attemptDeadServiceRecovery(e); - return sRouteOff; + return ROUTE_OFF; } } @@ -189,11 +195,11 @@ public final class NfcAdapterExtras { * <p class="note"> * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. * - * @param route a {@link #CardEmulationRoute} + * @param route a {@link CardEmulationRoute} */ public void setCardEmulationRoute(CardEmulationRoute route) { try { - sService.setCardEmulationRoute(route.route); + sService.setCardEmulationRoute(mPackageName, route.route); } catch (RemoteException e) { attemptDeadServiceRecovery(e); } @@ -201,7 +207,7 @@ public final class NfcAdapterExtras { /** * Get the {@link NfcExecutionEnvironment} that is embedded with the - * {@link NFcAdapter}. + * {@link NfcAdapter}. * * <p class="note"> * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. @@ -209,7 +215,7 @@ public final class NfcAdapterExtras { * @return a {@link NfcExecutionEnvironment}, or null if there is no embedded NFC-EE */ public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() { - return sEmbeddedEe; + return mEmbeddedEe; } /** @@ -218,12 +224,12 @@ public final class NfcAdapterExtras { * Some implementations of NFC Adapter Extras may require applications * to authenticate with a token, before using other methods. * - * @param a implementation specific token - * @throws a {@link java.lang.SecurityException} if authentication failed + * @param token a implementation specific token + * @throws java.lang.SecurityException if authentication failed */ public void authenticate(byte[] token) { try { - sService.authenticate(token); + sService.authenticate(mPackageName, token); } catch (RemoteException e) { attemptDeadServiceRecovery(e); } diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java index 63c2de200224..f47327aa2e79 100644 --- a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java +++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java @@ -16,20 +16,17 @@ package com.android.nfc_extras; -import java.io.IOException; - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; -import android.content.Context; -import android.nfc.INfcAdapterExtras; -import android.nfc.NfcAdapter; import android.os.Binder; import android.os.Bundle; -import android.os.IBinder; import android.os.RemoteException; +import java.io.IOException; + public class NfcExecutionEnvironment { private final NfcAdapterExtras mExtras; + private final Binder mToken; /** * Broadcast Action: An ISO-DEP AID was selected. @@ -115,6 +112,7 @@ public class NfcExecutionEnvironment { NfcExecutionEnvironment(NfcAdapterExtras extras) { mExtras = extras; + mToken = new Binder(); } /** @@ -133,7 +131,7 @@ public class NfcExecutionEnvironment { */ public void open() throws IOException { try { - Bundle b = mExtras.getService().open(new Binder()); + Bundle b = mExtras.getService().open(mExtras.mPackageName, mToken); throwBundle(b); } catch (RemoteException e) { mExtras.attemptDeadServiceRecovery(e); @@ -151,7 +149,7 @@ public class NfcExecutionEnvironment { */ public void close() throws IOException { try { - throwBundle(mExtras.getService().close()); + throwBundle(mExtras.getService().close(mExtras.mPackageName, mToken)); } catch (RemoteException e) { mExtras.attemptDeadServiceRecovery(e); throw new IOException("NFC Service was dead"); @@ -169,7 +167,7 @@ public class NfcExecutionEnvironment { public byte[] transceive(byte[] in) throws IOException { Bundle b; try { - b = mExtras.getService().transceive(in); + b = mExtras.getService().transceive(mExtras.mPackageName, in); } catch (RemoteException e) { mExtras.attemptDeadServiceRecovery(e); throw new IOException("NFC Service was dead, need to re-open"); diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk new file mode 100644 index 000000000000..3eca76d40504 --- /dev/null +++ b/nfc-extras/tests/Android.mk @@ -0,0 +1,32 @@ +# Copyright 2011, 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. + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# We only want this apk build for tests. +LOCAL_MODULE_TAGS := tests + +LOCAL_JAVA_LIBRARIES := \ + android.test.runner \ + com.android.nfc_extras + +# Include all test java files. +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := NfcExtrasTests + +LOCAL_SDK_VERSION := current + +include $(BUILD_PACKAGE) diff --git a/nfc-extras/tests/AndroidManifest.xml b/nfc-extras/tests/AndroidManifest.xml new file mode 100644 index 000000000000..0cc665343116 --- /dev/null +++ b/nfc-extras/tests/AndroidManifest.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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 name must be unique so suffix with "tests" so package loader doesn't ignore us --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.nfc_extras.tests"> + + <!-- We add an application tag here just so that we can indicate that + this package needs to link against the android.test library, + which is needed when building test cases. --> + <application> + <uses-library android:name="android.test.runner" /> + <uses-library android:name="com.android.nfc_extras" /> + </application> + + <uses-permission android:name="android.permission.NFC"/> + + <!-- + Run all tests with + adb shell am instrument -w com.android.nfc_extras.tests/android.test.InstrumentationTestRunner + --> + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.nfc_extras.tests" + android:label="Tests for NFC Extras library"/> + +</manifest> diff --git a/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java b/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java new file mode 100644 index 000000000000..e1025aa2e9b8 --- /dev/null +++ b/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2011 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 com.android.nfc_extras; + +import android.content.Context; +import android.nfc.NfcAdapter; +import android.test.InstrumentationTestCase; +import android.util.Log; + +import com.android.nfc_extras.NfcAdapterExtras; +import com.android.nfc_extras.NfcAdapterExtras.CardEmulationRoute; +import com.android.nfc_extras.NfcExecutionEnvironment; + +import java.io.IOException; +import java.util.Arrays; + +public class BasicNfcEeTest extends InstrumentationTestCase { + private Context mContext; + private NfcAdapterExtras mAdapterExtras; + private NfcExecutionEnvironment mEe; + + public static final byte[] SELECT_CARD_MANAGER_COMMAND = new byte[] { + (byte)0x00, (byte)0xA4, (byte)0x04, (byte)0x00, // command + (byte)0x08, // data length + (byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x00, + (byte)0x00, // card manager AID + (byte)0x00 // trailer + }; + + public static final byte[] SELECT_CARD_MANAGER_RESPONSE = new byte[] { + (byte)0x90, (byte)0x00, + }; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mContext = getInstrumentation().getContext(); + mAdapterExtras = NfcAdapterExtras.get(NfcAdapter.getDefaultAdapter(mContext)); + mEe = mAdapterExtras.getEmbeddedExecutionEnvironment(); + } + + public void testSendCardManagerApdu() throws IOException { + mEe.open(); + + try { + byte[] out = mEe.transceive(SELECT_CARD_MANAGER_COMMAND); + assertTrue(out.length >= SELECT_CARD_MANAGER_RESPONSE.length); + byte[] trailing = Arrays.copyOfRange(out, + out.length - SELECT_CARD_MANAGER_RESPONSE.length, + out.length); + assertByteArrayEquals(SELECT_CARD_MANAGER_RESPONSE, trailing); + + } finally { + mEe.close(); + } + + } + + public void testSendCardManagerApduMultiple() throws IOException { + for (int i=0; i<10; i++) { + try { + mEe.open(); + + try { + byte[] out = mEe.transceive(SELECT_CARD_MANAGER_COMMAND); + byte[] trailing = Arrays.copyOfRange(out, + out.length - SELECT_CARD_MANAGER_RESPONSE.length, + out.length); + + } finally { + try {Thread.sleep(1000);} catch (InterruptedException e) {} + mEe.close(); + } + } catch (IOException e) {} + } + + testSendCardManagerApdu(); + + } + + public void testEnableEe() { + mAdapterExtras.setCardEmulationRoute( + new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, mEe)); + CardEmulationRoute newRoute = mAdapterExtras.getCardEmulationRoute(); + assertEquals(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, newRoute.route); + assertEquals(mEe, newRoute.nfcEe); + } + + public void testDisableEe() { + mAdapterExtras.setCardEmulationRoute( + new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null)); + CardEmulationRoute newRoute = mAdapterExtras.getCardEmulationRoute(); + assertEquals(CardEmulationRoute.ROUTE_OFF, newRoute.route); + assertNull(newRoute.nfcEe); + } + + private static void assertByteArrayEquals(byte[] b1, byte[] b2) { + assertEquals(b1.length, b2.length); + for (int i = 0; i < b1.length; i++) { + assertEquals(b1[i], b2[i]); + } + } +} diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 8e8e26c0a849..c9266709ffa8 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -261,14 +261,14 @@ typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void); */ #ifndef EGL_ANDROID_blob_cache #define EGL_ANDROID_blob_cache 1 -typedef khronos_ssize_t EGLsizei; -typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, const void* value, EGLsizei valueSize); -typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, void* value, EGLsizei valueSize); +typedef khronos_ssize_t EGLsizeiANDROID; +typedef void (*EGLSetBlobFuncANDROID) (const void* key, EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize); +typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key, EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize); #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncs(EGLDisplay dpy, EGLSetBlobFunc set, EGLGetBlobFunc get); +EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); #endif /* EGL_EGLEXT_PROTOTYPES */ -typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy, - EGLSetBlobFunc set, EGLGetBlobFunc get); +typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, + EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); #endif #ifdef __cplusplus diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 60ac34b4a61e..63f02e49444b 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -860,7 +860,7 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) // The EGL_ANDROID_blob_cache extension should not be exposed to // applications. It is used internally by the Android EGL layer. - if (!strcmp(procname, "eglSetBlobCacheFuncs")) { + if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) { return NULL; } diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp index 522421b1d43f..13a492917d2c 100644 --- a/opengl/libs/EGL/egl_cache.cpp +++ b/opengl/libs/EGL/egl_cache.cpp @@ -46,13 +46,13 @@ namespace android { // // Callback functions passed to EGL. // -static void setBlob(const void* key, EGLsizei keySize, const void* value, - EGLsizei valueSize) { +static void setBlob(const void* key, EGLsizeiANDROID keySize, + const void* value, EGLsizeiANDROID valueSize) { egl_cache_t::get()->setBlob(key, keySize, value, valueSize); } -static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value, - EGLsizei valueSize) { +static EGLsizeiANDROID getBlob(const void* key, EGLsizeiANDROID keySize, + void* value, EGLsizeiANDROID valueSize) { return egl_cache_t::get()->getBlob(key, keySize, value, valueSize); } @@ -87,22 +87,23 @@ void egl_cache_t::initialize(egl_display_t *display) { !strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1)); bool inMiddle = strstr(" " BC_EXT_STR " ", exts); if (equal || atStart || atEnd || inMiddle) { - PFNEGLSETBLOBCACHEFUNCSPROC eglSetBlobCacheFuncs; - eglSetBlobCacheFuncs = - reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSPROC>( - cnx->egl.eglGetProcAddress("eglSetBlobCacheFuncs")); - if (eglSetBlobCacheFuncs == NULL) { + PFNEGLSETBLOBCACHEFUNCSANDROIDPROC eglSetBlobCacheFuncsANDROID; + eglSetBlobCacheFuncsANDROID = + reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>( + cnx->egl.eglGetProcAddress( + "eglSetBlobCacheFuncsANDROID")); + if (eglSetBlobCacheFuncsANDROID == NULL) { LOGE("EGL_ANDROID_blob_cache advertised by display %d, " - "but unable to get eglSetBlobCacheFuncs", i); + "but unable to get eglSetBlobCacheFuncsANDROID", i); continue; } - eglSetBlobCacheFuncs(display->disp[i].dpy, android::setBlob, - android::getBlob); + eglSetBlobCacheFuncsANDROID(display->disp[i].dpy, + android::setBlob, android::getBlob); EGLint err = cnx->egl.eglGetError(); if (err != EGL_SUCCESS) { - LOGE("eglSetBlobCacheFuncs resulted in an error: %#x", - err); + LOGE("eglSetBlobCacheFuncsANDROID resulted in an error: " + "%#x", err); } } } @@ -119,8 +120,8 @@ void egl_cache_t::terminate() { mInitialized = false; } -void egl_cache_t::setBlob(const void* key, EGLsizei keySize, const void* value, - EGLsizei valueSize) { +void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize, + const void* value, EGLsizeiANDROID valueSize) { Mutex::Autolock lock(mMutex); if (keySize < 0 || valueSize < 0) { @@ -158,8 +159,8 @@ void egl_cache_t::setBlob(const void* key, EGLsizei keySize, const void* value, } } -EGLsizei egl_cache_t::getBlob(const void* key, EGLsizei keySize, void* value, - EGLsizei valueSize) { +EGLsizeiANDROID egl_cache_t::getBlob(const void* key, EGLsizeiANDROID keySize, + void* value, EGLsizeiANDROID valueSize) { Mutex::Autolock lock(mMutex); if (keySize < 0 || valueSize < 0) { @@ -323,7 +324,8 @@ void egl_cache_t::loadBlobCacheLocked() { return; } - status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL, 0); + status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL, + 0); if (err != OK) { LOGE("error reading cache contents: %s (%d)", strerror(-err), -err); diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h index 4389623c5562..876000951c49 100644 --- a/opengl/libs/EGL/egl_cache.h +++ b/opengl/libs/EGL/egl_cache.h @@ -52,14 +52,14 @@ public: // setBlob attempts to insert a new key/value blob pair into the cache. // This will be called by the hardware vendor's EGL implementation via the // EGL_ANDROID_blob_cache extension. - void setBlob(const void* key, EGLsizei keySize, const void* value, - EGLsizei valueSize); + void setBlob(const void* key, EGLsizeiANDROID keySize, const void* value, + EGLsizeiANDROID valueSize); // getBlob attempts to retrieve the value blob associated with a given key // blob from cache. This will be called by the hardware vendor's EGL // implementation via the EGL_ANDROID_blob_cache extension. - EGLsizei getBlob(const void* key, EGLsizei keySize, void* value, - EGLsizei valueSize); + EGLsizeiANDROID getBlob(const void* key, EGLsizeiANDROID keySize, + void* value, EGLsizeiANDROID valueSize); // setCacheFilename sets the name of the file that should be used to store // cache contents from one program invocation to another. diff --git a/opengl/specs/EGL_ANDROID_blob_cache.txt b/opengl/specs/EGL_ANDROID_blob_cache.txt index 55dc9004a1fd..61f45d351878 100644 --- a/opengl/specs/EGL_ANDROID_blob_cache.txt +++ b/opengl/specs/EGL_ANDROID_blob_cache.txt @@ -63,33 +63,33 @@ Overview New Types /* - * EGLsizei is a signed integer type for representing the size of a memory - * buffer. + * EGLsizeiANDROID is a signed integer type for representing the size of a + * memory buffer. */ #include <khrplatform.h> - typedef khronos_ssize_t EGLsizei; + typedef khronos_ssize_t EGLsizeiANDROID; /* * EGLSetBlobFunc is a pointer to an application-provided function that a * client API implementation may use to insert a key/value pair into the * cache. */ - typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, - const void* value, EGLsizei valueSize) + typedef void (*EGLSetBlobFuncANDROID) (const void* key, + EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize) /* * EGLGetBlobFunc is a pointer to an application-provided function that a * client API implementation may use to retrieve a cached value from the * cache. */ - typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, - void* value, EGLsizei valueSize) + typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key, + EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize) New Procedures and Functions - void eglSetBlobCacheFuncs(EGLDisplay dpy, - EGLSetBlobFunc set, - EGLGetBlobFunc get); + void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, + EGLSetBlobFunc set, + EGLGetBlobFunc get); New Tokens @@ -107,8 +107,8 @@ Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) function pointers through which the client APIs can request data be cached and retrieved. The command - void eglSetBlobCacheFuncs(EGLDisplay dpy, - EGLSetBlobFunc set, EGLGetBlobFunc get); + void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, + EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); sets the callback function pointers that client APIs associated with display <dpy> can use to interact with caching functionality provided by @@ -120,17 +120,17 @@ Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) Cache functions may only be specified once during the lifetime of an EGLDisplay. The <set> and <get> functions may be called at any time and - from any thread from the time at which eglSetBlobCacheFuncs is called until - the time that the last resource associated with <dpy> is deleted and <dpy> - itself is terminated. Concurrent calls to these functions from different - threads is also allowed. - - If eglSetBlobCacheFuncs generates an error then all client APIs must behave - as though eglSetBlobCacheFuncs was not called for the display <dpy>. If - <set> or <get> is NULL then an EGL_BAD_PARAMETER error is generated. If a - successful eglSetBlobCacheFuncs call was already made for <dpy> and the - display has not since been terminated then an EGL_BAD_PARAMETER error is - generated. + from any thread from the time at which eglSetBlobCacheFuncsANDROID is + called until the time that the last resource associated with <dpy> is + deleted and <dpy> itself is terminated. Concurrent calls to these + functions from different threads is also allowed. + + If eglSetBlobCacheFuncsANDROID generates an error then all client APIs must + behave as though eglSetBlobCacheFuncsANDROID was not called for the display + <dpy>. If <set> or <get> is NULL then an EGL_BAD_PARAMETER error is + generated. If a successful eglSetBlobCacheFuncsANDROID call was already + made for <dpy> and the display has not since been terminated then an + EGL_BAD_PARAMETER error is generated. 3.9.1 Cache Operations @@ -138,8 +138,8 @@ Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) key, a client API implementation can call the application-provided callback function - void (*set) (const void* key, EGLsizei keySize, const void* value, - EGLsizei valueSize) + void (*set) (const void* key, EGLsizeiANDROID keySize, + const void* value, EGLsizeiANDROID valueSize) <key> and <value> are pointers to the beginning of the key and value, respectively, that are to be inserted. <keySize> and <valueSize> specify @@ -157,8 +157,8 @@ Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) client API implementation can call the application-provided callback function - EGLsizei (*get) (const void* key, EGLsizei keySize, void* value, - EGLsizei valueSize) + EGLsizeiANDROID (*get) (const void* key, EGLsizeiANDROID keySize, + void* value, EGLsizeiANDROID valueSize) <key> is a pointer to the beginning of the key. <keySize> specifies the size in bytes of the binary key pointed to by <key>. If the cache contains diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png Binary files differindex d697c2fdce63..cd9a54a904df 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png Binary files differindex 839c134a7598..5661eaf947f4 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png Binary files differindex 4f8c98711c90..98455cf5b558 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml index 3ee9e77e23a4..180f0228b5d3 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml @@ -33,39 +33,29 @@ android:clipToPadding="false" android:clipChildren="false"> - <LinearLayout android:id="@+id/recents_glow" + <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_gravity="bottom|right" + android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin" + android:divider="@null" + android:stackFromBottom="true" + android:fadingEdge="horizontal" + android:scrollbars="none" + android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" + android:layout_gravity="bottom|left" android:orientation="horizontal" android:clipToPadding="false" - android:clipChildren="false" - > - <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container" + android:clipChildren="false"> + + <LinearLayout android:id="@+id/recents_linear_layout" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin" - android:divider="@null" - android:stackFromBottom="true" - android:fadingEdge="horizontal" - android:scrollbars="none" - android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" - android:layout_gravity="bottom|left" android:orientation="horizontal" android:clipToPadding="false" android:clipChildren="false"> + </LinearLayout> - <LinearLayout android:id="@+id/recents_linear_layout" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:orientation="horizontal" - android:clipToPadding="false" - android:clipChildren="false"> - </LinearLayout> - - </com.android.systemui.recent.RecentsHorizontalScrollView> - - </LinearLayout> + </com.android.systemui.recent.RecentsHorizontalScrollView> </FrameLayout> diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml index d040544e63f0..e6a077a5e20a 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml @@ -31,39 +31,29 @@ android:layout_height="match_parent" android:layout_alignParentBottom="true"> - <LinearLayout android:id="@+id/recents_glow" + <com.android.systemui.recent.RecentsVerticalScrollView + android:id="@+id/recents_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:orientation="horizontal" - android:clipChildren="false" - android:layout_marginTop="@*android:dimen/status_bar_height"> + android:layout_marginRight="0dp" + android:divider="@null" + android:stackFromBottom="true" + android:fadingEdge="vertical" + android:scrollbars="none" + android:fadingEdgeLength="@*android:dimen/status_bar_height" + android:layout_gravity="bottom|left" + android:clipToPadding="false" + android:clipChildren="false"> - <com.android.systemui.recent.RecentsVerticalScrollView - android:id="@+id/recents_container" + <LinearLayout android:id="@+id/recents_linear_layout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginRight="0dp" - android:divider="@null" - android:stackFromBottom="true" - android:fadingEdge="vertical" - android:scrollbars="none" - android:fadingEdgeLength="@*android:dimen/status_bar_height" - android:layout_gravity="bottom|left" + android:orientation="vertical" android:clipToPadding="false" android:clipChildren="false"> + </LinearLayout> - <LinearLayout android:id="@+id/recents_linear_layout" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:clipToPadding="false" - android:clipChildren="false"> - </LinearLayout> - - </com.android.systemui.recent.RecentsVerticalScrollView> - - </LinearLayout> + </com.android.systemui.recent.RecentsVerticalScrollView> </FrameLayout> diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml new file mode 100644 index 000000000000..bc89281190de --- /dev/null +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* apps/common/assets/default/default/skins/StatusBar.xml +** +** Copyright 2011, 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. +*/ +--> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="match_parent" + android:layout_width="match_parent" + > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="20dp" + android:textColor="@android:color/holo_blue_light" + android:text="@string/status_bar_no_recent_apps" + android:gravity="left" + android:layout_gravity="bottom|left" + /> +</FrameLayout> diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml index 18a31f7dc136..cb26db00a54b 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml @@ -23,11 +23,26 @@ android:layout_height="wrap_content" android:layout_width="wrap_content"> - <FrameLayout android:id="@+id/app_thumbnail" - android:layout_width="wrap_content" + <TextView android:id="@+id/app_label" + android:layout_width="@dimen/status_bar_recents_app_label_width" android:layout_height="wrap_content" + android:textSize="@dimen/status_bar_recents_app_label_text_size" + android:fadingEdge="horizontal" + android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" + android:scrollHorizontally="true" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" + android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" + android:layout_marginTop="32dip" + android:singleLine="true" + android:ellipsize="marquee" + android:textColor="@color/status_bar_recents_app_label_color" + /> + + <FrameLayout android:id="@+id/app_thumbnail" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@id/app_label" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" android:background="@drawable/recents_thumbnail_bg" @@ -37,33 +52,22 @@ android:layout_width="@dimen/status_bar_recents_thumbnail_width" android:layout_height="@dimen/status_bar_recents_thumbnail_height" /> - <ImageView android:id="@+id/app_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin" - android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin" - android:maxWidth="@dimen/status_bar_recents_app_icon_max_width" - android:maxHeight="@dimen/status_bar_recents_app_icon_max_height" - android:adjustViewBounds="true" - /> </FrameLayout> - <TextView android:id="@+id/app_label" - android:layout_width="@dimen/status_bar_recents_app_label_width" + + <ImageView android:id="@+id/app_icon" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="@dimen/status_bar_recents_app_label_text_size" - android:fadingEdge="horizontal" - android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" - android:scrollHorizontally="true" - android:layout_alignParentLeft="true" - android:layout_alignParentTop="true" - android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" - android:layout_marginTop="32dip" - android:singleLine="true" - android:ellipsize="marquee" - android:textColor="@color/status_bar_recents_app_label_color" + android:layout_toRightOf="@id/app_label" + android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin" + android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin" + android:maxWidth="@dimen/status_bar_recents_app_icon_max_width" + android:maxHeight="@dimen/status_bar_recents_app_icon_max_height" + android:scaleType="centerInside" + android:adjustViewBounds="true" /> + <View android:id="@+id/recents_callout_line" android:layout_width="@dimen/status_bar_recents_app_label_width" android:layout_height="1dip" diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml index 5dd101e286a1..111f9a42de1c 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml @@ -36,40 +36,36 @@ android:clipToPadding="false" android:clipChildren="false"> - <LinearLayout android:id="@+id/recents_glow" + <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginBottom="-49dip" - android:layout_gravity="bottom" - android:background="@drawable/recents_blue_glow" - android:orientation="horizontal" + android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin" + android:divider="@null" + android:stackFromBottom="true" + android:fadingEdge="vertical" + android:scrollbars="none" + android:fadingEdgeLength="20dip" + android:layout_gravity="bottom|left" android:clipToPadding="false" - android:clipChildren="false" - > - <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container" + android:clipChildren="false"> + + <LinearLayout android:id="@+id/recents_linear_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin" - android:divider="@null" - android:stackFromBottom="true" - android:fadingEdge="vertical" - android:scrollbars="none" - android:fadingEdgeLength="20dip" - android:layout_gravity="bottom|left" + android:orientation="vertical" android:clipToPadding="false" android:clipChildren="false"> + </LinearLayout> - <LinearLayout android:id="@+id/recents_linear_layout" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - android:clipToPadding="false" - android:clipChildren="false"> - </LinearLayout> - - </com.android.systemui.recent.RecentsVerticalScrollView> + </com.android.systemui.recent.RecentsVerticalScrollView> - </LinearLayout> + <include layout="@layout/status_bar_no_recent_apps" + android:id="@+id/recents_no_apps" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginLeft="58dip" + android:layout_marginBottom="36dip" + android:visibility="invisible" /> </FrameLayout> @@ -82,4 +78,5 @@ android:contentDescription="@string/status_bar_accessibility_dismiss_recents" /> + </com.android.systemui.recent.RecentsPanelView> diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index af2c93c19f5a..b1aaade7c914 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -31,21 +31,35 @@ <LinearLayout android:id="@+id/icons" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="horizontal"> - - <com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons" + android:paddingLeft="6dip" + android:paddingRight="6dip" + android:orientation="horizontal" + > + + <LinearLayout android:layout_width="0dip" - android:layout_weight="1" android:layout_height="match_parent" - android:layout_alignParentLeft="true" - android:paddingLeft="6dip" - android:gravity="center_vertical" - android:orientation="horizontal"/> - + android:layout_weight="1" + android:orientation="horizontal" + > + <com.android.systemui.statusbar.StatusBarIconView android:id="@+id/moreIcon" + android:layout_width="@dimen/status_bar_icon_size" + android:layout_height="match_parent" + android:src="@drawable/stat_notify_more" + android:visibility="gone" + /> + + <com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentLeft="true" + android:gravity="center_vertical" + android:orientation="horizontal"/> + </LinearLayout> + <LinearLayout android:id="@+id/statusIcons" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_alignParentRight="true" android:gravity="center_vertical" android:orientation="horizontal"/> @@ -53,7 +67,7 @@ android:id="@+id/signal_battery_cluster" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_marginRight="6dp" + android:paddingLeft="2dp" android:orientation="horizontal" android:gravity="center" > @@ -66,7 +80,7 @@ android:id="@+id/battery" android:layout_height="wrap_content" android:layout_width="wrap_content" - android:paddingLeft="6dip" + android:paddingLeft="4dip" /> </LinearLayout> @@ -76,7 +90,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:singleLine="true" - android:paddingRight="6dip" + android:paddingLeft="6dip" android:gravity="center_vertical|left" /> </LinearLayout> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index 3e2ec5957812..24185a4f1844 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -18,8 +18,11 @@ --> <resources> - <!-- Whether we're using the tablet-optimized recents interface (we use this value at runtime for some things) --> <bool name="config_recents_interface_for_tablets">true</bool> + + <!-- Whether recents thumbnails should stretch in both x and y to fill their + ImageView --> + <bool name="config_recents_thumbnail_image_fits_to_xy">true</bool> </resources> diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index fe9245dda1fc..f522285a18a6 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -31,15 +31,15 @@ <!-- Recent Applications parameters --> <!-- How far the thumbnail for a recent app appears from left edge --> - <dimen name="status_bar_recents_thumbnail_left_margin">121dp</dimen> + <dimen name="status_bar_recents_thumbnail_left_margin">28dp</dimen> <!-- Upper width limit for application icon --> <dimen name="status_bar_recents_app_icon_max_width">64dp</dimen> <!-- Upper height limit for application icon --> <dimen name="status_bar_recents_app_icon_max_height">64dp</dimen> <!-- Size of application icon --> - <dimen name="status_bar_recents_thumbnail_width">245dp</dimen> - <dimen name="status_bar_recents_thumbnail_height">144dp</dimen> + <dimen name="status_bar_recents_thumbnail_width">208dp</dimen> + <dimen name="status_bar_recents_thumbnail_height">130dp</dimen> <!-- Width of recents panel --> <dimen name="status_bar_recents_width">600dp</dimen> @@ -59,8 +59,8 @@ <dimen name="status_bar_recents_right_glow_margin">100dip</dimen> <!-- Where to place the app icon over the thumbnail --> - <dimen name="status_bar_recents_app_icon_left_margin">13dp</dimen> - <dimen name="status_bar_recents_app_icon_top_margin">13dp</dimen> + <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen> + <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen> <!-- size at which Notification icons will be drawn in the status bar --> <dimen name="status_bar_icon_drawing_size">24dip</dimen> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 1fe4ebbb4102..1f225074c411 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -25,6 +25,10 @@ value at runtime for some things) --> <bool name="config_recents_interface_for_tablets">false</bool> + <!-- Whether recents thumbnails should stretch in both x and y to fill their + ImageView --> + <bool name="config_recents_thumbnail_image_fits_to_xy">false</bool> + <!-- Control whether status bar should distinguish HSPA data icon form UMTS data icon on devices --> <bool name="config_hspa_data_distinguishable">false</bool> diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java index 886a14d9e756..ad38a11a2a3c 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java +++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java @@ -120,8 +120,13 @@ import android.view.View; createAnimation(appearing); - mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null); - mContentView.buildLayer(); + // isHardwareAccelerated() checks if we're attached to a window and if that + // window is HW accelerated-- we were sometimes not attached to a window + // and buildLayer was throwing an IllegalStateException + if (mContentView.isHardwareAccelerated()) { + mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + mContentView.buildLayer(); + } mContentAnim.start(); mVisible = appearing; diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 6b8b65eab428..8bfd7111fb5a 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -16,14 +16,13 @@ package com.android.systemui.recent; -import java.util.ArrayList; - import android.animation.Animator; import android.animation.LayoutTransition; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.Shader.TileMode; @@ -42,15 +41,15 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AnimationUtils; import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.HorizontalScrollView; import android.widget.ImageView; +import android.widget.ImageView.ScaleType; import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.TextView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ImageView.ScaleType; import com.android.systemui.R; import com.android.systemui.statusbar.StatusBar; @@ -58,6 +57,8 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.tablet.StatusBarPanel; import com.android.systemui.statusbar.tablet.TabletStatusBar; +import java.util.ArrayList; + public class RecentsPanelView extends RelativeLayout implements OnItemClickListener, RecentsCallback, StatusBarPanel, Animator.AnimatorListener, View.OnTouchListener { static final String TAG = "RecentsPanelView"; @@ -65,7 +66,6 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe private Context mContext; private StatusBar mBar; private View mRecentsScrim; - private View mRecentsGlowView; private View mRecentsNoApps; private ViewGroup mRecentsContainer; @@ -79,6 +79,7 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe private boolean mRecentTasksDirty = true; private TaskDescriptionAdapter mListAdapter; private int mThumbnailWidth; + private boolean mFitThumbnailToXY; public void setRecentTasksLoader(RecentTasksLoader loader) { mRecentTasksLoader = loader; @@ -174,9 +175,8 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe // use mRecentsContainer's exact bounds to determine horizontal position final int l = mRecentsContainer.getLeft(); final int r = mRecentsContainer.getRight(); - // use surrounding mRecentsGlowView's position in parent determine vertical bounds - final int t = mRecentsGlowView.getTop(); - final int b = mRecentsGlowView.getBottom(); + final int t = mRecentsContainer.getTop(); + final int b = mRecentsContainer.getBottom(); return x >= l && x < r && y >= t && y < b; } @@ -194,7 +194,7 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe // if there are no apps, either bring up a "No recent apps" message, or just // quit early boolean noApps = (mRecentTaskDescriptions.size() == 0); - if (mRecentsNoApps != null) { // doesn't exist on large devices + if (mRecentsNoApps != null) { mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE); } else { if (noApps) { @@ -325,8 +325,9 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe } public void updateValuesFromResources() { - mThumbnailWidth = - (int) mContext.getResources().getDimension(R.dimen.status_bar_recents_thumbnail_width); + final Resources res = mContext.getResources(); + mThumbnailWidth = Math.round(res.getDimension(R.dimen.status_bar_recents_thumbnail_width)); + mFitThumbnailToXY = res.getBoolean(R.bool.config_recents_thumbnail_image_fits_to_xy); } @Override @@ -351,10 +352,9 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe } - mRecentsGlowView = findViewById(R.id.recents_glow); mRecentsScrim = findViewById(R.id.recents_bg_protect); mRecentsNoApps = findViewById(R.id.recents_no_apps); - mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView, mRecentsNoApps, this); + mChoreo = new Choreographer(this, mRecentsScrim, mRecentsContainer, mRecentsNoApps, this); mRecentsDismissButton = findViewById(R.id.recents_dismiss_button); if (mRecentsDismissButton != null) { mRecentsDismissButton.setOnClickListener(new OnClickListener() { @@ -409,11 +409,15 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe if (h.thumbnailViewImageBitmap == null || h.thumbnailViewImageBitmap.getWidth() != thumbnail.getWidth() || h.thumbnailViewImageBitmap.getHeight() != thumbnail.getHeight()) { - Matrix scaleMatrix = new Matrix(); - float scale = mThumbnailWidth / (float) thumbnail.getWidth(); - scaleMatrix.setScale(scale, scale); - h.thumbnailViewImage.setScaleType(ScaleType.MATRIX); - h.thumbnailViewImage.setImageMatrix(scaleMatrix); + if (mFitThumbnailToXY) { + h.thumbnailViewImage.setScaleType(ScaleType.FIT_XY); + } else { + Matrix scaleMatrix = new Matrix(); + float scale = mThumbnailWidth / (float) thumbnail.getWidth(); + scaleMatrix.setScale(scale, scale); + h.thumbnailViewImage.setScaleType(ScaleType.MATRIX); + h.thumbnailViewImage.setImageMatrix(scaleMatrix); + } } if (show && h.thumbnailView.getVisibility() != View.VISIBLE) { if (anim) { @@ -444,7 +448,7 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe // only fade in the thumbnail if recents is already visible-- we // show it immediately otherwise boolean animateShow = mShowing && - mRecentsGlowView.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD; + mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD; updateThumbnail(h, ad.getThumbnail(), true, animateShow); } } @@ -516,7 +520,6 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe final int items = mRecentTaskDescriptions.size(); mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE); - mRecentsGlowView.setVisibility(items > 0 ? View.VISIBLE : View.GONE); // Set description for accessibility int numRecentApps = mRecentTaskDescriptions.size(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 69978378d140..8228df5a1fcd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -25,6 +25,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.text.TextUtils; +import android.util.AttributeSet; import android.util.Slog; import android.util.Log; import android.view.ViewDebug; @@ -75,6 +76,18 @@ public class StatusBarIconView extends AnimatedImageView { setScaleType(ImageView.ScaleType.CENTER); } + public StatusBarIconView(Context context, AttributeSet attrs) { + super(context, attrs); + final Resources res = context.getResources(); + final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size); + final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size); + final float scale = (float)imageBounds / (float)outerBounds; + setScaleX(scale); + setScaleY(scale); + final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); + setAlpha(alpha); + } + private static boolean streq(String a, String b) { if (a == b) { return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java index 20215bd5cbf0..0640282422d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java @@ -30,113 +30,59 @@ import com.android.systemui.statusbar.StatusBarIconView; public class IconMerger extends LinearLayout { private static final String TAG = "IconMerger"; + private static final boolean DEBUG = false; private int mIconSize; - private StatusBarIconView mMoreView; - private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0, 0, - null); + private View mMoreView; public IconMerger(Context context, AttributeSet attrs) { super(context, attrs); mIconSize = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.status_bar_icon_size); + R.dimen.status_bar_icon_size); - mMoreView = new StatusBarIconView(context, "more", null); - mMoreView.set(mMoreIcon); - super.addView(mMoreView, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize)); + if (DEBUG) { + setBackgroundColor(0x800099FF); + } } - public void addView(StatusBarIconView v, int index, LinearLayout.LayoutParams p) { - super.addView(v, index+1, p); + public void setOverflowIndicator(View v) { + mMoreView = v; } - public void addView(StatusBarIconView v, int index) { - super.addView(v, index+1, new LinearLayout.LayoutParams(mIconSize, mIconSize)); + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + // we need to constrain this to an integral multiple of our children + int width = getMeasuredWidth(); + setMeasuredDimension(width - (width % mIconSize), getMeasuredHeight()); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); + checkOverflow(r - l); + } - final int maxWidth = r - l; - final int N = getChildCount(); - int i; - - // get the rightmost one, and see if we even need to do anything - int fitRight = -1; - for (i=N-1; i>=0; i--) { - final View child = getChildAt(i); - if (child.getVisibility() != GONE) { - fitRight = child.getRight(); - break; - } - } - - // find the first visible one that isn't the more icon - final StatusBarIconView moreView = mMoreView; - int fitLeft = -1; - int startIndex = -1; - for (i=0; i<N; i++) { - final View child = getChildAt(i); - if (child == moreView) { - startIndex = i+1; - } - else if (child.getVisibility() != GONE) { - fitLeft = child.getLeft(); - break; - } - } + private void checkOverflow(int width) { + if (mMoreView == null) return; - if (moreView == null || startIndex < 0) { - return; - /* - throw new RuntimeException("Status Bar / IconMerger moreView == " + moreView - + " startIndex=" + startIndex); - */ - } - - // if it fits without the more icon, then hide the more icon and update fitLeft - // so everything gets pushed left - int adjust = 0; - if (fitRight - fitLeft <= maxWidth) { - adjust = fitLeft - moreView.getLeft(); - fitLeft -= adjust; - fitRight -= adjust; - moreView.layout(0, moreView.getTop(), 0, moreView.getBottom()); + final int N = getChildCount(); + int visibleChildren = 0; + for (int i=0; i<N; i++) { + if (getChildAt(i).getVisibility() != GONE) visibleChildren++; } - int extra = fitRight - r; - int shift = -1; - - int breakingPoint = fitLeft + extra + adjust; - int number = 0; - for (i=startIndex; i<N; i++) { - final StatusBarIconView child = (StatusBarIconView)getChildAt(i); - if (child.getVisibility() != GONE) { - int childLeft = child.getLeft(); - int childRight = child.getRight(); - if (childLeft < breakingPoint) { - // hide this one - child.layout(0, child.getTop(), 0, child.getBottom()); - int n = child.getStatusBarIcon().number; - if (n == 0) { - number += 1; - } else if (n > 0) { - number += n; - } - } else { - // decide how much to shift by - if (shift < 0) { - shift = childLeft - fitLeft; - } - // shift this left by shift - child.layout(childLeft-shift, child.getTop(), - childRight-shift, child.getBottom()); + final boolean overflowShown = (mMoreView.getVisibility() == View.VISIBLE); + // let's assume we have one more slot if the more icon is already showing + if (overflowShown) visibleChildren --; + final boolean moreRequired = visibleChildren * mIconSize > width; + if (moreRequired != overflowShown) { + post(new Runnable() { + @Override + public void run() { + mMoreView.setVisibility(moreRequired ? View.VISIBLE : View.GONE); } - } + }); } - - mMoreIcon.number = number; - mMoreView.set(mMoreIcon); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 51fb262bff82..b0554d0278bc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -149,6 +149,7 @@ public class PhoneStatusBar extends StatusBar { // icons LinearLayout mIcons; IconMerger mNotificationIcons; + View mMoreIcon; LinearLayout mStatusIcons; // expanded notifications @@ -307,6 +308,8 @@ public class PhoneStatusBar extends StatusBar { mPixelFormat = PixelFormat.OPAQUE; mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons); mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons); + mMoreIcon = sb.findViewById(R.id.moreIcon); + mNotificationIcons.setOverflowIndicator(mMoreIcon); mIcons = (LinearLayout)sb.findViewById(R.id.icons); mTickerView = sb.findViewById(R.id.ticker); diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 0f21bdb475a4..dd3b75d2c7a4 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -244,8 +244,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // TODO: examine all widgets to derive clock status mUpdateMonitor.reportClockVisible(false); - // TODO: We should disable the wallpaper instead - setBackgroundColor(0xff000000); + // If there's not a bg protection view containing the transport, then show a black + // background. Otherwise, allow the normal background to show. + if (findViewById(R.id.transport_bg_protect) == null) { + // TODO: We should disable the wallpaper instead + setBackgroundColor(0xff000000); + } else { + resetBackground(); + } } public void requestHide(View view) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index ed9ba79f74d3..921f3313fb0f 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -360,6 +360,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mResettingSystemUiFlags = 0; // Bits that we are currently always keeping cleared. int mForceClearedSystemUiFlags = 0; + // What we last reported to system UI about whether the compatibility + // menu needs to be displayed. + boolean mLastFocusNeedsMenu = false; FakeWindow mHideNavFakeWindow = null; @@ -370,8 +373,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final Rect mTmpNavigationFrame = new Rect(); WindowState mTopFullscreenOpaqueWindowState; - WindowState mTopAppWindowState; - WindowState mLastTopAppWindowState; boolean mTopIsFullscreen; boolean mForceStatusBar; boolean mHideLockScreen; @@ -2250,7 +2251,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void beginAnimationLw(int displayWidth, int displayHeight) { mTopFullscreenOpaqueWindowState = null; - mTopAppWindowState = null; mForceStatusBar = false; mHideLockScreen = false; @@ -2288,12 +2288,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - if (mTopAppWindowState == null && win.isVisibleOrBehindKeyguardLw()) { - if (attrs.type >= FIRST_APPLICATION_WINDOW - && attrs.type <= LAST_APPLICATION_WINDOW) { - mTopAppWindowState = win; - } - } } /** {@inheritDoc} */ @@ -2349,35 +2343,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mTopIsFullscreen = topIsFullscreen; - if (mTopAppWindowState != null && mTopAppWindowState != mLastTopAppWindowState) { - mLastTopAppWindowState = mTopAppWindowState; - - final boolean topNeedsMenu = (mTopAppWindowState.getAttrs().flags - & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; - - mHandler.post(new Runnable() { - public void run() { - if (mStatusBarService == null) { - // This is the one that can not go away, but it doesn't come up - // before the window manager does, so don't fail if it doesn't - // exist. This works as long as no fullscreen windows come up - // before the status bar service does. - mStatusBarService = IStatusBarService.Stub.asInterface( - ServiceManager.getService("statusbar")); - } - final IStatusBarService sbs = mStatusBarService; - if (mStatusBarService != null) { - try { - sbs.topAppWindowChanged(topNeedsMenu); - } catch (RemoteException e) { - // This should be impossible because we're in the same process. - mStatusBarService = null; - } - } - } - }); - } - // Hide the key guard if a visible window explicitly specifies that it wants to be displayed // when the screen is locked if (mKeyguard != null) { @@ -3711,10 +3676,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { & ~mResettingSystemUiFlags & ~mForceClearedSystemUiFlags; int diff = visibility ^ mLastSystemUiFlags; - if (diff == 0) { + final boolean needsMenu = (mFocusedWindow.getAttrs().flags + & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; + if (diff == 0 && mLastFocusNeedsMenu == needsMenu) { return 0; } mLastSystemUiFlags = visibility; + mLastFocusNeedsMenu = needsMenu; mHandler.post(new Runnable() { public void run() { if (mStatusBarService == null) { @@ -3724,6 +3692,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mStatusBarService != null) { try { mStatusBarService.setSystemUiVisibility(visibility); + mStatusBarService.topAppWindowChanged(needsMenu); } catch (RemoteException e) { // not much to be done mStatusBarService = null; @@ -3756,6 +3725,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mForceClearedSystemUiFlags=0x"); pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); } + if (mLastFocusNeedsMenu) { + pw.print(prefix); pw.print("mLastFocusNeedsMenu="); + pw.println(mLastFocusNeedsMenu); + } pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); pw.print(" mDockMode="); pw.print(mDockMode); pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index ff262f12ab61..780c0d2c9b23 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -7028,11 +7028,17 @@ void AudioFlinger::EffectHandle::dump(char* buffer, size_t size) AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread, int sessionId) - : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), + : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0), mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX), mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX) { mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC); + sp<ThreadBase> thread = mThread.promote(); + if (thread == 0) { + return; + } + mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) / + thread->frameCount(); } AudioFlinger::EffectChain::~EffectChain() @@ -7100,22 +7106,31 @@ void AudioFlinger::EffectChain::process_l() } bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) || (mSessionId == AUDIO_SESSION_OUTPUT_STAGE); - bool tracksOnSession = false; + // always process effects unless no more tracks are on the session and the effect tail + // has been rendered + bool doProcess = true; if (!isGlobalSession) { - tracksOnSession = (trackCnt() != 0); - } + bool tracksOnSession = (trackCnt() != 0); - // if no track is active, input buffer must be cleared here as the mixer process - // will not do it - if (tracksOnSession && - activeTrackCnt() == 0) { - size_t numSamples = thread->frameCount() * thread->channelCount(); - memset(mInBuffer, 0, numSamples * sizeof(int16_t)); + if (!tracksOnSession && mTailBufferCount == 0) { + doProcess = false; + } + + if (activeTrackCnt() == 0) { + // if no track is active and the effect tail has not been rendered, + // the input buffer must be cleared here as the mixer process will not do it + if (tracksOnSession || mTailBufferCount > 0) { + size_t numSamples = thread->frameCount() * thread->channelCount(); + memset(mInBuffer, 0, numSamples * sizeof(int16_t)); + if (mTailBufferCount > 0) { + mTailBufferCount--; + } + } + } } size_t size = mEffects.size(); - // do not process effect if no track is present in same audio session - if (isGlobalSession || tracksOnSession) { + if (doProcess) { for (size_t i = 0; i < size; i++) { mEffects[i]->process(); } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 4b794ef59d38..897bc78396f5 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -1247,6 +1247,10 @@ private: // corresponding to a suspend all request. static const int kKeyForSuspendAll = 0; + // minimum duration during which we force calling effect process when last track on + // a session is stopped or removed to allow effect tail to be rendered + static const int kProcessTailDurationMs = 1000; + void process_l(); void lock() { @@ -1287,7 +1291,8 @@ private: void decTrackCnt() { android_atomic_dec(&mTrackCnt); } int32_t trackCnt() { return mTrackCnt;} - void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt); } + void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt); + mTailBufferCount = mMaxTailBuffers; } void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); } int32_t activeTrackCnt() { return mActiveTrackCnt;} @@ -1338,6 +1343,8 @@ private: int16_t *mOutBuffer; // chain output buffer volatile int32_t mActiveTrackCnt; // number of active tracks connected volatile int32_t mTrackCnt; // number of tracks connected + int32_t mTailBufferCount; // current effect tail buffer count + int32_t mMaxTailBuffers; // maximum effect tail buffers bool mOwnInBuffer; // true if the chain owns its input buffer int mVolumeCtrlIdx; // index of insert effect having control over volume uint32_t mLeftVolume; // previous volume on left channel diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 05d42ada146c..39e8c726b6ed 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1248,7 +1248,14 @@ public final class ActivityManagerService extends ActivityManagerNative PrintWriter pw = new PrintWriter(sw); StringWriter catSw = new StringWriter(); PrintWriter catPw = new PrintWriter(catSw); - dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true, catPw); + String[] emptyArgs = new String[] { }; + dumpApplicationMemoryUsage(null, pw, " ", emptyArgs, true, catPw); + pw.println(); + dumpProcessesLocked(null, pw, emptyArgs, 0, false); + pw.println(); + dumpServicesLocked(null, pw, emptyArgs, 0, false, false); + pw.println(); + dumpActivitiesLocked(null, pw, emptyArgs, 0, false, false); String memUsage = sw.toString(); dropBuilder.append('\n'); dropBuilder.append(memUsage); @@ -1479,6 +1486,7 @@ public final class ActivityManagerService extends ActivityManagerNative mConfiguration.setToDefaults(); mConfiguration.locale = Locale.getDefault(); + mConfigurationSeq = mConfiguration.seq = 1; mProcessStats.init(); mCompatModePackages = new CompatModePackages(this, systemDir); @@ -1669,7 +1677,7 @@ public final class ActivityManagerService extends ActivityManagerNative final void setFocusedActivityLocked(ActivityRecord r) { if (mFocusedActivity != r) { mFocusedActivity = r; - mWindowManager.setFocusedApp(r, true); + mWindowManager.setFocusedApp(r.appToken, true); } } @@ -2346,7 +2354,8 @@ public final class ActivityManagerService extends ActivityManagerNative // XXX we are not dealing with propagating grantedUriPermissions... // those are not yet exposed to user code, so there is no need. int res = mMainStack.startActivityLocked(r.app.thread, intent, - r.resolvedType, null, 0, aInfo, resultTo, resultWho, + r.resolvedType, null, 0, aInfo, + resultTo != null ? resultTo.appToken : null, resultWho, requestCode, -1, r.launchedFromUid, false, false, null); Binder.restoreCallingIdentity(origId); @@ -2429,13 +2438,13 @@ public final class ActivityManagerService extends ActivityManagerNative return; } final long origId = Binder.clearCallingIdentity(); - mWindowManager.setAppOrientation(r, requestedOrientation); + mWindowManager.setAppOrientation(r.appToken, requestedOrientation); Configuration config = mWindowManager.updateOrientationFromAppTokens( mConfiguration, - r.mayFreezeScreenLocked(r.app) ? r : null); + r.mayFreezeScreenLocked(r.app) ? r.appToken : null); if (config != null) { r.frozenBeforeDestroy = true; - if (!updateConfigurationLocked(config, r, false)) { + if (!updateConfigurationLocked(config, r, false, false)) { mMainStack.resumeTopActivityLocked(null); } } @@ -2449,7 +2458,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (r == null) { return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; } - return mWindowManager.getAppOrientation(r); + return mWindowManager.getAppOrientation(r.appToken); } } @@ -2515,7 +2524,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i<activities.size(); i++) { ActivityRecord r = activities.get(i); if (!r.finishing) { - int index = mMainStack.indexOfTokenLocked(r); + int index = mMainStack.indexOfTokenLocked(r.appToken); if (index >= 0) { mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED, null, "finish-heavy"); @@ -2617,7 +2626,7 @@ public final class ActivityManagerService extends ActivityManagerNative int i; for (i=mMainStack.mHistory.size()-1; i>=0; i--) { ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); - if (r == token) { + if (r.appToken == token) { return true; } if (r.fullscreen && !r.finishing) { @@ -2705,9 +2714,9 @@ public final class ActivityManagerService extends ActivityManagerNative r.makeFinishing(); mMainStack.mHistory.remove(i); r.takeFromHistory(); - mWindowManager.removeAppToken(r); + mWindowManager.removeAppToken(r.appToken); if (VALIDATE_TOKENS) { - mWindowManager.validateAppTokens(mMainStack.mHistory); + mMainStack.validateAppTokensLocked(); } r.removeUriPermissionsLocked(); @@ -3796,7 +3805,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.instrumentationClass, profileFile, profileFd, profileAutoStop, app.instrumentationArguments, app.instrumentationWatcher, testMode, isRestrictedBackupMode || !normalMode, app.persistent, - mConfiguration, app.compat, getCommonServicesLocked(), + new Configuration(mConfiguration), app.compat, getCommonServicesLocked(), mCoreSettingsObserver.getCoreSettingsLocked()); updateLruProcessLocked(app, false, true); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); @@ -5173,10 +5182,10 @@ public final class ActivityManagerService extends ActivityManagerNative if (topThumbnail != null) { if (localLOGV) Slog.v(TAG, "Requesting top thumbnail"); try { - topThumbnail.requestThumbnail(topRecord); + topThumbnail.requestThumbnail(topRecord.appToken); } catch (Exception e) { Slog.w(TAG, "Exception thrown when requesting thumbnail", e); - sendPendingThumbnail(null, topRecord, null, null, true); + sendPendingThumbnail(null, topRecord.appToken, null, null, true); } } @@ -5547,7 +5556,7 @@ public final class ActivityManagerService extends ActivityManagerNative TaskRecord lastTask = null; for (int i=0; i<N; i++) { ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); - if (r == token) { + if (r.appToken == token) { if (!onlyRoot || lastTask != r.task) { return r.task.taskId; } @@ -5568,7 +5577,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i<N; i++) { ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); if (r.realActivity.equals(className) - && r != token && lastTask != r.task) { + && r.appToken != token && lastTask != r.task) { if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "others")) { i--; @@ -6706,8 +6715,7 @@ public final class ActivityManagerService extends ActivityManagerNative mAlwaysFinishActivities = alwaysFinishActivities; // This happens before any activities are started, so we can // change mConfiguration in-place. - mConfiguration.updateFrom(configuration); - mConfigurationSeq = mConfiguration.seq = 1; + updateConfigurationLocked(configuration, null, false, true); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration); } } @@ -7112,7 +7120,7 @@ public final class ActivityManagerService extends ActivityManagerNative // process, then terminate it to avoid getting in a loop. Slog.w(TAG, " Force finishing activity " + r.intent.getComponent().flattenToShortString()); - int index = mMainStack.indexOfTokenLocked(r); + int index = mMainStack.indexOfActivityLocked(r); r.stack.finishActivityLocked(r, index, Activity.RESULT_CANCELED, null, "crashed"); // Also terminate any activities below it that aren't yet @@ -8631,8 +8639,8 @@ public final class ActivityManagerService extends ActivityManagerNative try { TransferPipe tp = new TransferPipe(); try { - r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r, - innerPrefix, args); + r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), + r.appToken, innerPrefix, args); tp.go(fd); } finally { tp.kill(); @@ -8788,6 +8796,20 @@ public final class ActivityManagerService extends ActivityManagerNative TimeUtils.formatDuration(r.createTime, nowReal, pw); pw.print(" started="); pw.print(r.startRequested); pw.print(" connections="); pw.println(r.connections.size()); + if (r.connections.size() > 0) { + pw.println(" Connections:"); + for (ArrayList<ConnectionRecord> clist : r.connections.values()) { + for (int i=0; i<clist.size(); i++) { + ConnectionRecord conn = clist.get(i); + pw.print(" "); + pw.print(conn.binding.intent.intent.getIntent().toShortString( + false, false, false)); + pw.print(" -> "); + ProcessRecord proc = conn.binding.client; + pw.println(proc != null ? proc.toShortString() : "null"); + } + } + } } if (dumpClient && r.app != null && r.app.thread != null) { pw.println(" Client:"); @@ -8907,18 +8929,21 @@ public final class ActivityManagerService extends ActivityManagerNative continue; } pw.print(" * "); pw.print(cls); pw.print(" ("); - pw.print(comp.flattenToShortString()); pw.print(")"); + pw.print(comp.flattenToShortString()); pw.println(")"); if (dumpAll) { - pw.println(); r.dump(pw, " "); } else { - pw.print(" * "); pw.print(e.getKey().flattenToShortString()); if (r.proc != null) { - pw.println(":"); pw.print(" "); pw.println(r.proc); } else { pw.println(); } + if (r.clients.size() > 0) { + pw.println(" Clients:"); + for (ProcessRecord cproc : r.clients) { + pw.print(" - "); pw.println(cproc); + } + } } } needSep = true; @@ -9048,8 +9073,8 @@ public final class ActivityManagerService extends ActivityManagerNative try { TransferPipe tp = new TransferPipe(); try { - r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r, - innerPrefix, args); + r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), + r.appToken, innerPrefix, args); // Short timeout, since blocking here can // deadlock with the application. tp.go(fd, 2000); @@ -12933,7 +12958,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(this) { final long origId = Binder.clearCallingIdentity(); - updateConfigurationLocked(values, null, true); + updateConfigurationLocked(values, null, true, false); Binder.restoreCallingIdentity(origId); } } @@ -12956,7 +12981,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (values != null) { Settings.System.clearConfiguration(values); } - updateConfigurationLocked(values, null, false); + updateConfigurationLocked(values, null, false, false); Binder.restoreCallingIdentity(origId); } } @@ -12970,7 +12995,7 @@ public final class ActivityManagerService extends ActivityManagerNative * @param persistent TODO */ public boolean updateConfigurationLocked(Configuration values, - ActivityRecord starting, boolean persistent) { + ActivityRecord starting, boolean persistent, boolean initLocale) { int changes = 0; boolean kept = true; @@ -12985,7 +13010,7 @@ public final class ActivityManagerService extends ActivityManagerNative EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes); - if (values.locale != null) { + if (values.locale != null && !initLocale) { saveLocaleLocked(values.locale, !values.locale.equals(mConfiguration.locale), values.userSetLocale); @@ -12998,10 +13023,12 @@ public final class ActivityManagerService extends ActivityManagerNative newConfig.seq = mConfigurationSeq; mConfiguration = newConfig; Slog.i(TAG, "Config changed: " + newConfig); - + + final Configuration configCopy = new Configuration(mConfiguration); + AttributeCache ac = AttributeCache.instance(); if (ac != null) { - ac.updateConfiguration(mConfiguration); + ac.updateConfiguration(configCopy); } // Make sure all resources in our process are updated @@ -13011,11 +13038,11 @@ public final class ActivityManagerService extends ActivityManagerNative // boot, where the first config change needs to guarantee // all resources have that config before following boot // code is executed. - mSystemThread.applyConfigurationToResources(newConfig); + mSystemThread.applyConfigurationToResources(configCopy); if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) { Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG); - msg.obj = new Configuration(mConfiguration); + msg.obj = new Configuration(configCopy); mHandler.sendMessage(msg); } @@ -13025,7 +13052,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.thread != null) { if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc " + app.processName + " new config " + mConfiguration); - app.thread.scheduleConfigurationChanged(mConfiguration); + app.thread.scheduleConfigurationChanged(configCopy); } } catch (Exception e) { } diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 00e6cb294ca1..951a946e06a0 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -29,6 +29,7 @@ import android.content.res.Configuration; import android.graphics.Bitmap; import android.os.Build; import android.os.Bundle; +import android.os.IBinder; import android.os.Message; import android.os.Process; import android.os.RemoteException; @@ -48,9 +49,10 @@ import java.util.HashSet; /** * An entry in the history stack, representing an activity. */ -final class ActivityRecord extends IApplicationToken.Stub { +final class ActivityRecord { final ActivityManagerService service; // owner final ActivityStack stack; // owner + final IApplicationToken.Stub appToken; // window manager token final ActivityInfo info; // all about me final int launchedFromUid; // always the uid who started the activity. final Intent intent; // the original intent that generated us @@ -200,6 +202,70 @@ final class ActivityRecord extends IApplicationToken.Stub { } } + static class Token extends IApplicationToken.Stub { + final WeakReference<ActivityRecord> weakActivity; + + Token(ActivityRecord activity) { + weakActivity = new WeakReference<ActivityRecord>(activity); + } + + @Override public void windowsDrawn() throws RemoteException { + ActivityRecord activity = weakActivity.get(); + if (activity != null) { + activity.windowsDrawn(); + } + } + + @Override public void windowsVisible() throws RemoteException { + ActivityRecord activity = weakActivity.get(); + if (activity != null) { + activity.windowsVisible(); + } + } + + @Override public void windowsGone() throws RemoteException { + ActivityRecord activity = weakActivity.get(); + if (activity != null) { + activity.windowsGone(); + } + } + + @Override public boolean keyDispatchingTimedOut() throws RemoteException { + ActivityRecord activity = weakActivity.get(); + if (activity != null) { + return activity.keyDispatchingTimedOut(); + } + return false; + } + + @Override public long getKeyDispatchingTimeout() throws RemoteException { + ActivityRecord activity = weakActivity.get(); + if (activity != null) { + return activity.getKeyDispatchingTimeout(); + } + return 0; + } + + public String toString() { + StringBuilder sb = new StringBuilder(128); + sb.append("Token{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(' '); + sb.append(weakActivity.get()); + sb.append('}'); + return sb.toString(); + } + } + + static ActivityRecord forToken(IBinder token) { + try { + return token != null ? ((Token)token).weakActivity.get() : null; + } catch (ClassCastException e) { + Slog.w(ActivityManagerService.TAG, "Bad activity token: " + token, e); + return null; + } + } + ActivityRecord(ActivityManagerService _service, ActivityStack _stack, ProcessRecord _caller, int _launchedFromUid, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, @@ -207,6 +273,7 @@ final class ActivityRecord extends IApplicationToken.Stub { boolean _componentSpecified) { service = _service; stack = _stack; + appToken = new Token(this); info = aInfo; launchedFromUid = _launchedFromUid; intent = _intent; @@ -445,7 +512,7 @@ final class ActivityRecord extends IApplicationToken.Stub { ar.add(intent); service.grantUriPermissionFromIntentLocked(callingUid, packageName, intent, getUriPermissionsLocked()); - app.thread.scheduleNewIntent(ar, this); + app.thread.scheduleNewIntent(ar, appToken); sent = true; } catch (RemoteException e) { Slog.w(ActivityManagerService.TAG, @@ -470,14 +537,14 @@ final class ActivityRecord extends IApplicationToken.Stub { void pauseKeyDispatchingLocked() { if (!keysPaused) { keysPaused = true; - service.mWindowManager.pauseKeyDispatching(this); + service.mWindowManager.pauseKeyDispatching(appToken); } } void resumeKeyDispatchingLocked() { if (keysPaused) { keysPaused = false; - service.mWindowManager.resumeKeyDispatching(this); + service.mWindowManager.resumeKeyDispatching(appToken); } } @@ -512,14 +579,14 @@ final class ActivityRecord extends IApplicationToken.Stub { public void startFreezingScreenLocked(ProcessRecord app, int configChanges) { if (mayFreezeScreenLocked(app)) { - service.mWindowManager.startAppFreezingScreen(this, configChanges); + service.mWindowManager.startAppFreezingScreen(appToken, configChanges); } } public void stopFreezingScreenLocked(boolean force) { if (force || frozenBeforeDestroy) { frozenBeforeDestroy = false; - service.mWindowManager.stopAppFreezingScreen(this, force); + service.mWindowManager.stopAppFreezingScreen(appToken, force); } } @@ -687,7 +754,7 @@ final class ActivityRecord extends IApplicationToken.Stub { } if (app != null && app.thread != null) { try { - app.thread.scheduleSleeping(this, _sleeping); + app.thread.scheduleSleeping(appToken, _sleeping); if (sleeping && !stack.mGoingToSleepActivities.contains(this)) { stack.mGoingToSleepActivities.add(this); } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 8435eaa029e2..c7ce3c3eed8d 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -145,7 +145,12 @@ final class ActivityStack { * running) activities. It contains HistoryRecord objects. */ final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>(); - + + /** + * Used for validating app tokens with window manager. + */ + final ArrayList<IBinder> mValidateAppTokens = new ArrayList<IBinder>(); + /** * List of running activities, sorted by recent usage. * The first entry in the list is the least recently used. @@ -294,11 +299,11 @@ final class ActivityStack { } } break; case PAUSE_TIMEOUT_MSG: { - IBinder token = (IBinder)msg.obj; + ActivityRecord r = (ActivityRecord)msg.obj; // We don't at this point know if the activity is fullscreen, // so we need to be conservative and assume it isn't. - Slog.w(TAG, "Activity pause timeout for " + token); - activityPaused(token, true); + Slog.w(TAG, "Activity pause timeout for " + r); + activityPaused(r != null ? r.appToken : null, true); } break; case IDLE_TIMEOUT_MSG: { if (mService.mDidDexOpt) { @@ -310,20 +315,20 @@ final class ActivityStack { } // We don't at this point know if the activity is fullscreen, // so we need to be conservative and assume it isn't. - IBinder token = (IBinder)msg.obj; - Slog.w(TAG, "Activity idle timeout for " + token); - activityIdleInternal(token, true, null); + ActivityRecord r = (ActivityRecord)msg.obj; + Slog.w(TAG, "Activity idle timeout for " + r); + activityIdleInternal(r != null ? r.appToken : null, true, null); } break; case DESTROY_TIMEOUT_MSG: { - IBinder token = (IBinder)msg.obj; + ActivityRecord r = (ActivityRecord)msg.obj; // We don't at this point know if the activity is fullscreen, // so we need to be conservative and assume it isn't. - Slog.w(TAG, "Activity destroy timeout for " + token); - activityDestroyed(token); + Slog.w(TAG, "Activity destroy timeout for " + r); + activityDestroyed(r != null ? r.appToken : null); } break; case IDLE_NOW_MSG: { - IBinder token = (IBinder)msg.obj; - activityIdleInternal(token, false, null); + ActivityRecord r = (ActivityRecord)msg.obj; + activityIdleInternal(r != null ? r.appToken : null, false, null); } break; case LAUNCH_TIMEOUT_MSG: { if (mService.mDidDexOpt) { @@ -397,7 +402,7 @@ final class ActivityStack { while (i >= 0) { ActivityRecord r = mHistory.get(i); // Note: the taskId check depends on real taskId fields being non-zero - if (!r.finishing && (token != r) && (taskId != r.task.taskId)) { + if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)) { return r; } i--; @@ -406,23 +411,17 @@ final class ActivityStack { } final int indexOfTokenLocked(IBinder token) { - try { - ActivityRecord r = (ActivityRecord)token; - return mHistory.indexOf(r); - } catch (ClassCastException e) { - Slog.w(TAG, "Bad activity token: " + token, e); - return -1; - } + return mHistory.indexOf(ActivityRecord.forToken(token)); + } + + final int indexOfActivityLocked(ActivityRecord r) { + return mHistory.indexOf(r); } final ActivityRecord isInStackLocked(IBinder token) { - try { - ActivityRecord r = (ActivityRecord)token; - if (mHistory.contains(r)) { - return r; - } - } catch (ClassCastException e) { - Slog.w(TAG, "Bad activity token: " + token, e); + ActivityRecord r = ActivityRecord.forToken(token); + if (mHistory.contains(r)) { + return r; } return null; } @@ -517,7 +516,7 @@ final class ActivityStack { throws RemoteException { r.startFreezingScreenLocked(app, 0); - mService.mWindowManager.setAppVisibility(r, true); + mService.mWindowManager.setAppVisibility(r.appToken, true); // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. Note that @@ -528,8 +527,8 @@ final class ActivityStack { if (checkConfig) { Configuration config = mService.mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, - r.mayFreezeScreenLocked(app) ? r : null); - mService.updateConfigurationLocked(config, r, false); + r.mayFreezeScreenLocked(app) ? r.appToken : null); + mService.updateConfigurationLocked(config, r, false, false); } r.app = app; @@ -590,8 +589,9 @@ final class ActivityStack { profileFd = null; } } - app.thread.scheduleLaunchActivity(new Intent(r.intent), r, - System.identityHashCode(r), r.info, mService.mConfiguration, + app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, + System.identityHashCode(r), r.info, + new Configuration(mService.mConfiguration), r.compat, r.icicle, results, newIntents, !andResume, mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop); @@ -624,7 +624,7 @@ final class ActivityStack { + r.intent.getComponent().flattenToShortString() + ", giving up", e); mService.appDiedLocked(app, app.pid, app.thread); - requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null, + requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash"); return false; } @@ -821,7 +821,7 @@ final class ActivityStack { } if (w > 0) { - return mService.mWindowManager.screenshotApplications(who, w, h); + return mService.mWindowManager.screenshotApplications(who.appToken, w, h); } return null; } @@ -856,8 +856,8 @@ final class ActivityStack { EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY, System.identityHashCode(prev), prev.shortComponentName); - prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving, - prev.configChangeFlags); + prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, + userLeaving, prev.configChangeFlags); if (mMainStack) { mService.updateUsageStats(prev, false); } @@ -1129,7 +1129,7 @@ final class ActivityStack { if (!r.visible) { if (DEBUG_VISBILITY) Slog.v( TAG, "Starting and making visible: " + r); - mService.mWindowManager.setAppVisibility(r, true); + mService.mWindowManager.setAppVisibility(r.appToken, true); } if (r != starting) { startSpecificActivityLocked(r, false, false); @@ -1153,10 +1153,10 @@ final class ActivityStack { if (DEBUG_VISBILITY) Slog.v( TAG, "Making visible and scheduling visibility: " + r); try { - mService.mWindowManager.setAppVisibility(r, true); + mService.mWindowManager.setAppVisibility(r.appToken, true); r.sleeping = false; r.app.pendingUiClean = true; - r.app.thread.scheduleWindowVisibility(r, true); + r.app.thread.scheduleWindowVisibility(r.appToken, true); r.stopFreezingScreenLocked(false); } catch (Exception e) { // Just skip on any failure; we'll make it @@ -1195,13 +1195,13 @@ final class ActivityStack { TAG, "Making invisible: " + r); r.visible = false; try { - mService.mWindowManager.setAppVisibility(r, false); + mService.mWindowManager.setAppVisibility(r.appToken, false); if ((r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) && r.app != null && r.app.thread != null) { if (DEBUG_VISBILITY) Slog.v( TAG, "Scheduling invisibility: " + r); - r.app.thread.scheduleWindowVisibility(r, false); + r.app.thread.scheduleWindowVisibility(r.appToken, false); } } catch (Exception e) { // Just skip on any failure; we'll make it @@ -1351,7 +1351,7 @@ final class ActivityStack { // previous should actually be hidden depending on whether the // new one is found to be full-screen or not. if (prev.finishing) { - mService.mWindowManager.setAppVisibility(prev, false); + mService.mWindowManager.setAppVisibility(prev.appToken, false); if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: " + prev + ", waitingVisible=" + (prev != null ? prev.waitingVisible : null) @@ -1399,8 +1399,8 @@ final class ActivityStack { ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE : WindowManagerPolicy.TRANSIT_TASK_CLOSE, false); } - mService.mWindowManager.setAppWillBeHidden(prev); - mService.mWindowManager.setAppVisibility(prev, false); + mService.mWindowManager.setAppWillBeHidden(prev.appToken); + mService.mWindowManager.setAppVisibility(prev.appToken, false); } else { if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev); @@ -1414,8 +1414,8 @@ final class ActivityStack { } } if (false) { - mService.mWindowManager.setAppWillBeHidden(prev); - mService.mWindowManager.setAppVisibility(prev, false); + mService.mWindowManager.setAppWillBeHidden(prev.appToken); + mService.mWindowManager.setAppVisibility(prev.appToken, false); } } else if (mHistory.size() > 1) { if (DEBUG_TRANSITION) Slog.v(TAG, @@ -1433,7 +1433,7 @@ final class ActivityStack { if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next); // This activity is now becoming visible. - mService.mWindowManager.setAppVisibility(next, true); + mService.mWindowManager.setAppVisibility(next.appToken, true); ActivityRecord lastResumedActivity = mResumedActivity; ActivityState lastState = next.state; @@ -1457,11 +1457,11 @@ final class ActivityStack { synchronized (mService) { Configuration config = mService.mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, - next.mayFreezeScreenLocked(next.app) ? next : null); + next.mayFreezeScreenLocked(next.app) ? next.appToken : null); if (config != null) { next.frozenBeforeDestroy = true; } - updated = mService.updateConfigurationLocked(config, next, false); + updated = mService.updateConfigurationLocked(config, next, false, false); } } if (!updated) { @@ -1496,12 +1496,12 @@ final class ActivityStack { if (DEBUG_RESULTS) Slog.v( TAG, "Delivering results to " + next + ": " + a); - next.app.thread.scheduleSendResult(next, a); + next.app.thread.scheduleSendResult(next.appToken, a); } } if (next.newIntents != null) { - next.app.thread.scheduleNewIntent(next.newIntents, next); + next.app.thread.scheduleNewIntent(next.newIntents, next.appToken); } EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, @@ -1511,7 +1511,7 @@ final class ActivityStack { next.sleeping = false; showAskCompatModeDialogLocked(next); next.app.pendingUiClean = true; - next.app.thread.scheduleResumeActivity(next, + next.app.thread.scheduleResumeActivity(next.appToken, mService.isNextTransitionForward()); checkReadyForSleepLocked(); @@ -1528,7 +1528,7 @@ final class ActivityStack { } else { if (SHOW_APP_STARTING_PREVIEW && mMainStack) { mService.mWindowManager.setAppStartingWindow( - next, next.packageName, next.theme, + next.appToken, next.packageName, next.theme, mService.compatibilityInfoForPackageLocked( next.info.applicationInfo), next.nonLocalizedLabel, @@ -1549,7 +1549,7 @@ final class ActivityStack { // If any exception gets thrown, toss away this // activity and try the next one. Slog.w(TAG, "Exception thrown during resume of " + next, e); - requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null, + requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, "resume-exception"); return true; } @@ -1567,7 +1567,7 @@ final class ActivityStack { } else { if (SHOW_APP_STARTING_PREVIEW) { mService.mWindowManager.setAppStartingWindow( - next, next.packageName, next.theme, + next.appToken, next.packageName, next.theme, mService.compatibilityInfoForPackageLocked( next.info.applicationInfo), next.nonLocalizedLabel, @@ -1610,10 +1610,10 @@ final class ActivityStack { } mHistory.add(addPos, r); r.putInHistory(); - mService.mWindowManager.addAppToken(addPos, r, r.task.taskId, + mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen); if (VALIDATE_TOKENS) { - mService.mWindowManager.validateAppTokens(mHistory); + validateAppTokensLocked(); } return; } @@ -1677,7 +1677,7 @@ final class ActivityStack { mNoAnimActivities.remove(r); } mService.mWindowManager.addAppToken( - addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen); + addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen); boolean doShow = true; if (newTask) { // Even though this activity is starting fresh, we still need @@ -1705,19 +1705,20 @@ final class ActivityStack { else if (prev.nowVisible) prev = null; } mService.mWindowManager.setAppStartingWindow( - r, r.packageName, r.theme, + r.appToken, r.packageName, r.theme, mService.compatibilityInfoForPackageLocked( r.info.applicationInfo), r.nonLocalizedLabel, - r.labelRes, r.icon, r.windowFlags, prev, showStartingIcon); + r.labelRes, r.icon, r.windowFlags, + prev != null ? prev.appToken : null, showStartingIcon); } } else { // If this is the first activity, don't do any fancy animations, // because there is nothing for it to animate on top of. - mService.mWindowManager.addAppToken(addPos, r, r.task.taskId, + mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen); } if (VALIDATE_TOKENS) { - mService.mWindowManager.validateAppTokens(mHistory); + validateAppTokensLocked(); } if (doResume) { @@ -1725,6 +1726,15 @@ final class ActivityStack { } } + final void validateAppTokensLocked() { + mValidateAppTokens.clear(); + mValidateAppTokens.ensureCapacity(mHistory.size()); + for (int i=0; i<mHistory.size(); i++) { + mValidateAppTokens.add(mHistory.get(i).appToken); + } + mService.mWindowManager.validateAppTokens(mValidateAppTokens); + } + /** * Perform a reset of the given task, if needed as part of launching it. * Returns the new HistoryRecord at the top of the task. @@ -1826,7 +1836,7 @@ final class ActivityStack { if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target + " out to new task " + target.task); } - mService.mWindowManager.setAppGroupId(target, task.taskId); + mService.mWindowManager.setAppGroupId(target.appToken, task.taskId); if (replyChainEnd < 0) { replyChainEnd = targetI; } @@ -1849,11 +1859,11 @@ final class ActivityStack { } mHistory.remove(srcPos); mHistory.add(dstPos, p); - mService.mWindowManager.moveAppToken(dstPos, p); - mService.mWindowManager.setAppGroupId(p, p.task.taskId); + mService.mWindowManager.moveAppToken(dstPos, p.appToken); + mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId); dstPos++; if (VALIDATE_TOKENS) { - mService.mWindowManager.validateAppTokens(mHistory); + validateAppTokensLocked(); } i++; } @@ -1985,10 +1995,10 @@ final class ActivityStack { mHistory.add(lastReparentPos, p); if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " in to resetting task " + task); - mService.mWindowManager.moveAppToken(lastReparentPos, p); - mService.mWindowManager.setAppGroupId(p, p.task.taskId); + mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken); + mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId); if (VALIDATE_TOKENS) { - mService.mWindowManager.validateAppTokens(mHistory); + validateAppTokensLocked(); } } replyChainEnd = -1; @@ -2081,7 +2091,7 @@ final class ActivityStack { if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) { if (!ret.finishing) { - int index = indexOfTokenLocked(ret); + int index = indexOfTokenLocked(ret.appToken); if (index >= 0) { finishActivityLocked(ret, index, Activity.RESULT_CANCELED, null, "clear"); @@ -2908,7 +2918,7 @@ final class ActivityStack { mConfigWillChange = false; if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating to new configuration after starting activity."); - mService.updateConfigurationLocked(config, null, false); + mService.updateConfigurationLocked(config, null, false, false); } Binder.restoreCallingIdentity(origId); @@ -3007,7 +3017,7 @@ final class ActivityStack { return res; } - resultTo = outActivity[0]; + resultTo = outActivity[0] != null ? outActivity[0].appToken : null; } } } finally { @@ -3065,7 +3075,7 @@ final class ActivityStack { ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); list.add(new ResultInfo(resultWho, requestCode, resultCode, data)); - r.app.thread.scheduleSendResult(r, list); + r.app.thread.scheduleSendResult(r.appToken, list); return; } catch (Exception e) { Slog.w(TAG, "Exception thrown sending result to " + r, e); @@ -3080,7 +3090,7 @@ final class ActivityStack { if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { if (!r.finishing) { - requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null, + requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "no-history"); } } else if (r.app != null && r.app.thread != null) { @@ -3098,9 +3108,9 @@ final class ActivityStack { if (DEBUG_VISBILITY) Slog.v( TAG, "Stopping visible=" + r.visible + " for " + r); if (!r.visible) { - mService.mWindowManager.setAppVisibility(r, false); + mService.mWindowManager.setAppVisibility(r.appToken, false); } - r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags); + r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); if (mService.isSleeping()) { r.setSleeping(true); } @@ -3145,7 +3155,7 @@ final class ActivityStack { // normal flow and hide it once we determine that it is // hidden by the activities in front of it. if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s); - mService.mWindowManager.setAppVisibility(s, false); + mService.mWindowManager.setAppVisibility(s.appToken, false); } } if ((!s.waitingVisible || mService.isSleeping()) && remove) { @@ -3186,14 +3196,14 @@ final class ActivityStack { boolean enableScreen = false; synchronized (mService) { - if (token != null) { - mHandler.removeMessages(IDLE_TIMEOUT_MSG, token); + ActivityRecord r = ActivityRecord.forToken(token); + if (r != null) { + mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); } // Get the activity record. - int index = indexOfTokenLocked(token); + int index = indexOfActivityLocked(r); if (index >= 0) { - ActivityRecord r = mHistory.get(index); res = r; if (fromTimeout) { @@ -3413,7 +3423,7 @@ final class ActivityStack { : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE, false); // Tell window manager to prepare for this one to be removed. - mService.mWindowManager.setAppVisibility(r, false); + mService.mWindowManager.setAppVisibility(r.appToken, false); if (mPausingActivity == null) { if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r); @@ -3440,7 +3450,7 @@ final class ActivityStack { private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode) { - final int index = indexOfTokenLocked(r); + final int index = indexOfActivityLocked(r); if (index < 0) { return null; } @@ -3570,9 +3580,9 @@ final class ActivityStack { if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (removed from history)"); r.state = ActivityState.DESTROYED; - mService.mWindowManager.removeAppToken(r); + mService.mWindowManager.removeAppToken(r.appToken); if (VALIDATE_TOKENS) { - mService.mWindowManager.validateAppTokens(mHistory); + validateAppTokensLocked(); } cleanUpActivityServicesLocked(r); r.removeUriPermissionsLocked(); @@ -3653,7 +3663,7 @@ final class ActivityStack { try { if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r); - r.app.thread.scheduleDestroyActivity(r, r.finishing, + r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing, r.configChangeFlags); } catch (Exception e) { // We can just ignore exceptions here... if the process @@ -3712,11 +3722,13 @@ final class ActivityStack { final void activityDestroyed(IBinder token) { synchronized (mService) { - mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token); + ActivityRecord r = ActivityRecord.forToken(token); + if (r != null) { + mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); + } - int index = indexOfTokenLocked(token); + int index = indexOfActivityLocked(r); if (index >= 0) { - ActivityRecord r = mHistory.get(index); if (r.state == ActivityState.DESTROYING) { final long origId = Binder.clearCallingIdentity(); removeActivityFromHistoryLocked(r); @@ -3781,7 +3793,7 @@ final class ActivityStack { return; } - ArrayList moved = new ArrayList(); + ArrayList<IBinder> moved = new ArrayList<IBinder>(); // Applying the affinities may have removed entries from the history, // so get the size again. @@ -3803,7 +3815,7 @@ final class ActivityStack { } mHistory.remove(pos); mHistory.add(top, r); - moved.add(0, r); + moved.add(0, r.appToken); top--; } pos--; @@ -3826,7 +3838,7 @@ final class ActivityStack { mService.mWindowManager.moveAppTokensToTop(moved); if (VALIDATE_TOKENS) { - mService.mWindowManager.validateAppTokens(mHistory); + validateAppTokensLocked(); } finishTaskMoveLocked(task); @@ -3873,7 +3885,7 @@ final class ActivityStack { } } - ArrayList moved = new ArrayList(); + ArrayList<IBinder> moved = new ArrayList<IBinder>(); if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to back transition: task=" + task); @@ -3898,7 +3910,7 @@ final class ActivityStack { } mHistory.remove(pos); mHistory.add(bottom, r); - moved.add(r); + moved.add(r.appToken); bottom++; } pos++; @@ -3918,7 +3930,7 @@ final class ActivityStack { } mService.mWindowManager.moveAppTokensToBottom(moved); if (VALIDATE_TOKENS) { - mService.mWindowManager.validateAppTokens(mHistory); + validateAppTokensLocked(); } finishTaskMoveLocked(task); @@ -4148,7 +4160,7 @@ final class ActivityStack { if (r.app != null && r.app.thread != null) { try { if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r); - r.app.thread.scheduleActivityConfigurationChanged(r); + r.app.thread.scheduleActivityConfigurationChanged(r.appToken); } catch (RemoteException e) { // If process died, whatever. } @@ -4178,8 +4190,8 @@ final class ActivityStack { try { if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r); r.forceNewConfig = false; - r.app.thread.scheduleRelaunchActivity(r, results, newIntents, - changes, !andResume, mService.mConfiguration); + r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, + changes, !andResume, new Configuration(mService.mConfiguration)); // Note: don't need to call pauseIfSleepingLocked() here, because // the caller will only pass in 'andResume' if this activity is // currently resumed, which implies we aren't sleeping. diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java index 9c55597530d2..6f6266d8100c 100644 --- a/services/java/com/android/server/am/ContentProviderRecord.java +++ b/services/java/com/android/server/am/ContentProviderRecord.java @@ -74,6 +74,10 @@ class ContentProviderRecord extends ContentProviderHolder { pw.print(" initOrder="); pw.println(info.initOrder); } if (clients.size() > 0) { + pw.print(prefix); pw.println("Clients:"); + for (ProcessRecord cproc : clients) { + pw.print(prefix); pw.println(" - "); pw.println(cproc); + } pw.print(prefix); pw.print("clients="); pw.println(clients); } if (externals != 0) { diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 423a78fff4b8..c344bc6770a3 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -73,7 +73,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private Context mContext; private final static String TAG = "Tethering"; private final static boolean DBG = true; - private final static boolean VDBG = true; + private final static boolean VDBG = false; // TODO - remove both of these - should be part of interface inspection/selection stuff private String[] mTetherableUsbRegexs; @@ -228,7 +228,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (isUsb(iface)) { // ignore usb0 down after enabling RNDIS // we will handle disconnect in interfaceRemoved instead - if (VDBG) Log.d(TAG, "ignoring interface down for " + iface); + if (VDBG) Log.d(TAG, "ignore interface down for " + iface); } else if (sm != null) { sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); mIfaces.remove(iface); @@ -298,7 +298,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { mIfaces.put(iface, sm); sm.start(); } - if (VDBG) Log.d(TAG, "interfaceAdded :" + iface); } public void interfaceRemoved(String iface) { @@ -415,7 +414,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList); mContext.sendStickyBroadcast(broadcast); - if (VDBG) { + if (DBG) { Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + activeList.size() + ", " + erroredList.size()); } @@ -865,7 +864,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { @Override public boolean processMessage(Message message) { - if (VDBG) Log.d(TAG, "InitialState.processMessage what=" + message.what); + if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_REQUESTED: @@ -906,7 +905,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - if (VDBG) Log.d(TAG, "StartingState.processMessage what=" + message.what); + if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { // maybe a parent class? @@ -985,7 +984,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { @Override public boolean processMessage(Message message) { - if (VDBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what); + if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what); boolean retValue = true; boolean error = false; switch (message.what) { @@ -1061,7 +1060,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { ConnectivityManager.TETHER_ERROR_MASTER_ERROR); break; } - if (VDBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName); + if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName); sendTetherStateChangedBroadcast(); if (mUsb) { if (!Tethering.this.configureUsbIface(false)) { @@ -1296,7 +1295,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } } - if (VDBG) { + if (DBG) { Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn =" + mPreferredUpstreamMobileApn + ", got type=" + upType); } @@ -1328,7 +1327,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { - if (VDBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName); + if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName); mUpstreamIfaceName = ifaceName; for (Object o : mNotifyList) { TetherInterfaceSM sm = (TetherInterfaceSM)o; @@ -1344,7 +1343,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - if (VDBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); + if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_MODE_REQUESTED: @@ -1386,7 +1385,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - if (VDBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); + if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_MODE_REQUESTED: diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 63655258fe5a..28cb983ad18f 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -1243,7 +1243,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // trim any history beyond max if (mTime.hasCache()) { - final long currentTime = mTime.currentTimeMillis(); + final long currentTime = Math.min( + System.currentTimeMillis(), mTime.currentTimeMillis()); final long maxHistory = mSettings.getNetworkMaxHistory(); for (NetworkStatsHistory history : input.values()) { history.removeBucketsBefore(currentTime - maxHistory); @@ -1287,7 +1288,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // trim any history beyond max if (mTime.hasCache()) { - final long currentTime = mTime.currentTimeMillis(); + final long currentTime = Math.min( + System.currentTimeMillis(), mTime.currentTimeMillis()); final long maxUidHistory = mSettings.getUidMaxHistory(); final long maxTagHistory = mSettings.getTagMaxHistory(); for (UidStatsKey key : mUidStats.keySet()) { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 4ffc20199272..ebb13d5c8f61 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -3070,7 +3070,7 @@ public class WindowManagerService extends IWindowManager.Stub // Application Window Tokens // ------------------------------------------------------------- - public void validateAppTokens(List tokens) { + public void validateAppTokens(List<IBinder> tokens) { int v = tokens.size()-1; int m = mAppTokens.size()-1; while (v >= 0 && m >= 0) { @@ -5090,10 +5090,22 @@ public class WindowManagerService extends IWindowManager.Stub // Constrain thumbnail to smaller of screen width or height. Assumes aspect // of thumbnail is the same as the screen (in landscape) or square. + float targetWidthScale = width / (float) fw; + float targetHeightScale = height / (float) fh; if (dw <= dh) { - scale = width / (float) fw; // portrait + scale = targetWidthScale; + // If aspect of thumbnail is the same as the screen (in landscape), + // select the slightly larger value so we fill the entire bitmap + if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { + scale = targetHeightScale; + } } else { - scale = height / (float) fh; // landscape + scale = targetHeightScale; + // If aspect of thumbnail is the same as the screen (in landscape), + // select the slightly larger value so we fill the entire bitmap + if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { + scale = targetWidthScale; + } } // The screen shot will contain the entire screen. diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java index 368595f98ae3..061837478a5d 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -80,7 +80,6 @@ import com.google.common.util.concurrent.AbstractFuture; import org.easymock.Capture; import org.easymock.EasyMock; import org.easymock.IAnswer; -import org.easymock.IExpectationSetters; import java.io.File; import java.util.LinkedHashSet; @@ -537,6 +536,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10)) .andReturn(stats).atLeastOnce(); + expectPolicyDataEnable(TYPE_WIFI, true); // TODO: consider making strongly ordered mock expectRemoveInterfaceQuota(TEST_IFACE); @@ -580,7 +580,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { NetworkState[] state = null; NetworkStats stats = null; Future<Void> future; - Capture<String> tag; + Future<String> tagFuture; final long TIME_FEB_15 = 1171497600000L; final long TIME_MAR_10 = 1173484800000L; @@ -598,6 +598,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) .andReturn(stats).atLeastOnce(); + expectPolicyDataEnable(TYPE_WIFI, true); expectClearNotifications(); future = expectMeteredIfacesChanged(); @@ -620,6 +621,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) .andReturn(stats).atLeastOnce(); + expectPolicyDataEnable(TYPE_WIFI, true); expectRemoveInterfaceQuota(TEST_IFACE); expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES); @@ -642,14 +644,15 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expectCurrentTime(); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) .andReturn(stats).atLeastOnce(); + expectPolicyDataEnable(TYPE_WIFI, true); expectForceUpdate(); expectClearNotifications(); - tag = expectEnqueueNotification(); + tagFuture = expectEnqueueNotification(); replay(); mNetworkObserver.limitReached(null, TEST_IFACE); - assertNotificationType(TYPE_WARNING, tag.getValue()); + assertNotificationType(TYPE_WARNING, tagFuture.get()); verifyAndReset(); } @@ -662,15 +665,15 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expectCurrentTime(); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) .andReturn(stats).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, false).atLeastOnce(); + expectPolicyDataEnable(TYPE_WIFI, false); expectForceUpdate(); expectClearNotifications(); - tag = expectEnqueueNotification(); + tagFuture = expectEnqueueNotification(); replay(); mNetworkObserver.limitReached(null, TEST_IFACE); - assertNotificationType(TYPE_LIMIT, tag.getValue()); + assertNotificationType(TYPE_LIMIT, tagFuture.get()); verifyAndReset(); } @@ -682,21 +685,20 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) .andReturn(stats).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, true).atLeastOnce(); + expectPolicyDataEnable(TYPE_WIFI, true); // snoozed interface still has high quota so background data is // still restricted. expectRemoveInterfaceQuota(TEST_IFACE); expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE); + expectMeteredIfacesChanged(TEST_IFACE); expectClearNotifications(); - tag = expectEnqueueNotification(); - future = expectMeteredIfacesChanged(TEST_IFACE); + tagFuture = expectEnqueueNotification(); replay(); mService.snoozePolicy(sTemplateWifi); - future.get(); - assertNotificationType(TYPE_LIMIT_SNOOZED, tag.getValue()); + assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get()); verifyAndReset(); } } @@ -737,9 +739,9 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expectLastCall().anyTimes(); } - private Capture<String> expectEnqueueNotification() throws Exception { - final Capture<String> tag = new Capture<String>(); - mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag), anyInt(), + private Future<String> expectEnqueueNotification() throws Exception { + final FutureCapture<String> tag = new FutureCapture<String>(); + mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag.capture), anyInt(), isA(Notification.class), isA(int[].class)); return tag; } @@ -789,22 +791,25 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { return future; } - private <T> IExpectationSetters<T> expectPolicyDataEnable(int type, boolean enabled) - throws Exception { + private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception { + final FutureAnswer future = new FutureAnswer(); mConnManager.setPolicyDataEnable(type, enabled); - return expectLastCall(); + expectLastCall().andAnswer(future); + return future; } - private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> { + private static class TestAbstractFuture<T> extends AbstractFuture<T> { @Override - public Void get() throws InterruptedException, ExecutionException { + public T get() throws InterruptedException, ExecutionException { try { return get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { throw new RuntimeException(e); } } + } + private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> { @Override public Void answer() { set(null); @@ -812,6 +817,16 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { } } + private static class FutureCapture<T> extends TestAbstractFuture<T> { + public Capture<T> capture = new Capture<T>() { + @Override + public void setValue(T value) { + super.setValue(value); + set(value); + } + }; + } + private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler { @Override public Void get() throws InterruptedException, ExecutionException { diff --git a/telephony/java/com/android/internal/telephony/cat/CatService.java b/telephony/java/com/android/internal/telephony/cat/CatService.java index 542026498eaa..5a994f3de061 100644 --- a/telephony/java/com/android/internal/telephony/cat/CatService.java +++ b/telephony/java/com/android/internal/telephony/cat/CatService.java @@ -94,6 +94,8 @@ public class CatService extends Handler implements AppInterface { private static final int DEV_ID_TERMINAL = 0x82; private static final int DEV_ID_NETWORK = 0x83; + static final String STK_DEFAULT = "Defualt Message"; + /* Intentionally private for singleton */ private CatService(CommandsInterface ci, IccRecords ir, Context context, IccFileHandler fh, IccCard ic) { @@ -157,7 +159,15 @@ public class CatService extends Handler implements AppInterface { } break; case MSG_ID_PROACTIVE_COMMAND: - cmdParams = (CommandParams) rilMsg.mData; + try { + cmdParams = (CommandParams) rilMsg.mData; + } catch (ClassCastException e) { + // for error handling : cast exception + CatLog.d(this, "Fail to parse proactive command"); + sendTerminalResponse(mCurrntCmd.mCmdDet, ResultCode.CMD_DATA_NOT_UNDERSTOOD, + false, 0x00, null); + break; + } if (cmdParams != null) { if (rilMsg.mResCode == ResultCode.OK) { handleProactiveCommand(cmdParams); @@ -194,6 +204,7 @@ public class CatService extends Handler implements AppInterface { private void handleProactiveCommand(CommandParams cmdParams) { CatLog.d(this, cmdParams.getCommandType().name()); + CharSequence message; CatCmdMessage cmdMsg = new CatCmdMessage(cmdParams); switch (cmdParams.getCommandType()) { case SET_UP_MENU: @@ -224,26 +235,44 @@ public class CatService extends Handler implements AppInterface { case CommandParamsFactory.DTTZ_SETTING: resp = new DTTZResponseData(null); sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp); - break; + return; case CommandParamsFactory.LANGUAGE_SETTING: resp = new LanguageResponseData(Locale.getDefault().getLanguage()); sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp); - break; + return; default: sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null); return; } case LAUNCH_BROWSER: + if ((((LaunchBrowserParams) cmdParams).confirmMsg.text != null) + && (((LaunchBrowserParams) cmdParams).confirmMsg.text.equals(STK_DEFAULT))) { + message = mContext.getText(com.android.internal.R.string.launchBrowserDefault); + ((LaunchBrowserParams) cmdParams).confirmMsg.text = message.toString(); + } + break; case SELECT_ITEM: case GET_INPUT: case GET_INKEY: + break; case SEND_DTMF: case SEND_SMS: case SEND_SS: case SEND_USSD: + if ((((DisplayTextParams)cmdParams).textMsg.text != null) + && (((DisplayTextParams)cmdParams).textMsg.text.equals(STK_DEFAULT))) { + message = mContext.getText(com.android.internal.R.string.sending); + ((DisplayTextParams)cmdParams).textMsg.text = message.toString(); + } + break; case PLAY_TONE: + break; case SET_UP_CALL: - // nothing to do on telephony! + if ((((CallSetupParams) cmdParams).confirmMsg.text != null) + && (((CallSetupParams) cmdParams).confirmMsg.text.equals(STK_DEFAULT))) { + message = mContext.getText(com.android.internal.R.string.SetupCallDefault); + ((CallSetupParams) cmdParams).confirmMsg.text = message.toString(); + } break; default: CatLog.d(this, "Unsupported command"); diff --git a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java index 686fe4646542..e7fca5a8b936 100644 --- a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java +++ b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java @@ -403,6 +403,7 @@ class CommandParamsFactory extends Handler { input.ucs2 = (cmdDet.commandQualifier & 0x02) != 0; input.yesNo = (cmdDet.commandQualifier & 0x04) != 0; input.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0; + input.echo = true; mCmdParams = new GetInputParams(cmdDet, input); @@ -625,11 +626,7 @@ class CommandParamsFactory extends Handler { ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs); - if (ctlv != null) { - textMsg.text = ValueParser.retrieveAlphaId(ctlv); - } else { - throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING); - } + textMsg.text = ValueParser.retrieveAlphaId(ctlv); ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); if (ctlv != null) { @@ -714,9 +711,8 @@ class CommandParamsFactory extends Handler { // parse alpha identifier. ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs); - if (ctlv != null) { - confirmMsg.text = ValueParser.retrieveAlphaId(ctlv); - } + confirmMsg.text = ValueParser.retrieveAlphaId(ctlv); + // parse icon identifier ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); if (ctlv != null) { @@ -841,9 +837,7 @@ class CommandParamsFactory extends Handler { // get confirmation message string. ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter); - if (ctlv != null) { - confirmMsg.text = ValueParser.retrieveAlphaId(ctlv); - } + confirmMsg.text = ValueParser.retrieveAlphaId(ctlv); ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); if (ctlv != null) { diff --git a/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java b/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java index e5a2d31e5562..ab26d13a5931 100644 --- a/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java +++ b/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java @@ -94,6 +94,7 @@ class ComprehensionTlv { startIndex = ctlv.mValueIndex + ctlv.mLength; } else { CatLog.d(LOG_TAG, "decodeMany: ctlv is null, stop decoding"); + items.clear(); break; } } @@ -123,7 +124,10 @@ class ComprehensionTlv { case 0: case 0xff: case 0x80: - throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); + // for error handling + // these one make exception while decoding the abnormal command. + // (in case of Ghana MTN simcard , JDI simcard) + return null; case 0x7f: // tag is in three-byte format tag = ((data[curIndex] & 0xff) << 8) diff --git a/telephony/java/com/android/internal/telephony/cat/ValueParser.java b/telephony/java/com/android/internal/telephony/cat/ValueParser.java index 34e48112f4d8..584d96cb522f 100644 --- a/telephony/java/com/android/internal/telephony/cat/ValueParser.java +++ b/telephony/java/com/android/internal/telephony/cat/ValueParser.java @@ -273,18 +273,23 @@ abstract class ValueParser { */ static String retrieveAlphaId(ComprehensionTlv ctlv) throws ResultException { - byte[] rawValue = ctlv.getRawValue(); - int valueIndex = ctlv.getValueIndex(); - int length = ctlv.getLength(); - if (length != 0) { - try { - return IccUtils.adnStringFieldToString(rawValue, valueIndex, - length); - } catch (IndexOutOfBoundsException e) { - throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); + if (ctlv != null) { + byte[] rawValue = ctlv.getRawValue(); + int valueIndex = ctlv.getValueIndex(); + int length = ctlv.getLength(); + if (length != 0) { + try { + return IccUtils.adnStringFieldToString(rawValue, valueIndex, + length); + } catch (IndexOutOfBoundsException e) { + throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); + } + } else { + return CatService.STK_DEFAULT; } + } else { + return CatService.STK_DEFAULT; } - return null; } /** |