summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/app/ActivityThread.java324
-rw-r--r--core/java/android/app/LoadedApk.java7
-rw-r--r--core/java/android/app/WallpaperManager.java3
-rw-r--r--core/java/android/bluetooth/BluetoothDeviceProfileState.java2
-rw-r--r--core/java/android/bluetooth/IBluetooth.aidl2
-rw-r--r--core/java/android/content/res/XmlBlock.java6
-rw-r--r--core/java/android/hardware/Camera.java43
-rw-r--r--core/java/android/nfc/INfcAdapter.aidl2
-rw-r--r--core/java/android/nfc/INfcAdapterExtras.aidl12
-rw-r--r--core/java/android/nfc/NfcAdapter.java78
-rw-r--r--core/java/android/nfc/NfcManager.java3
-rw-r--r--core/java/android/provider/ContactsContract.java10
-rw-r--r--core/java/android/server/BluetoothEventLoop.java3
-rwxr-xr-xcore/java/android/server/BluetoothService.java65
-rw-r--r--core/java/android/webkit/WebView.java28
-rw-r--r--core/java/android/widget/EdgeEffect.java2
-rw-r--r--core/java/android/widget/TextView.java43
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java2
-rw-r--r--core/java/com/android/internal/widget/DigitalClock.java3
-rw-r--r--core/jni/android/graphics/SurfaceTexture.cpp6
-rw-r--r--core/jni/android/graphics/TextLayoutCache.cpp2
-rw-r--r--core/res/res/drawable-hdpi/transportcontrol_bg.9.pngbin0 -> 4210 bytes
-rw-r--r--core/res/res/drawable-mdpi/transportcontrol_bg.9.pngbin0 -> 2462 bytes
-rw-r--r--core/res/res/drawable-xhdpi/transportcontrol_bg.9.pngbin0 -> 6659 bytes
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml113
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml51
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_status_land.xml29
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_status_port.xml29
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml37
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml39
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml51
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml76
-rw-r--r--core/res/res/layout-sw600dp/keyguard_transport_control.xml111
-rw-r--r--core/res/res/layout/screen_action_bar.xml2
-rw-r--r--core/res/res/layout/screen_action_bar_overlay.xml53
-rw-r--r--core/res/res/layout/screen_simple.xml2
-rw-r--r--core/res/res/layout/screen_simple_overlay_action_mode.xml2
-rw-r--r--core/res/res/values-af/strings.xml6
-rw-r--r--core/res/res/values-da/strings.xml2
-rw-r--r--core/res/res/values-es-rUS/strings.xml4
-rw-r--r--core/res/res/values-iw/strings.xml12
-rw-r--r--core/res/res/values-ko/strings.xml8
-rw-r--r--core/res/res/values-ru/strings.xml2
-rw-r--r--core/res/res/values-sw600dp/dimens.xml2
-rw-r--r--core/res/res/values-zu/strings.xml10
-rwxr-xr-xcore/res/res/values/strings.xml11
-rw-r--r--core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java83
-rw-r--r--core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java51
-rw-r--r--core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java4
-rw-r--r--docs/html/guide/developing/building/building-cmdline.jd2
-rw-r--r--docs/html/guide/topics/resources/drawable-resource.jd22
-rw-r--r--docs/html/sdk/ndk/index.jd323
-rw-r--r--docs/html/sdk/sdk_toc.cs3
-rw-r--r--graphics/java/android/graphics/Bitmap.java7
-rw-r--r--graphics/java/android/graphics/SurfaceTexture.java14
-rw-r--r--graphics/java/android/renderscript/RSSurfaceView.java8
-rw-r--r--include/gui/SurfaceTexture.h12
-rw-r--r--include/media/MediaProfiles.h20
-rw-r--r--libs/gui/tests/SurfaceTexture_test.cpp32
-rw-r--r--media/java/android/media/AudioService.java32
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java1
-rw-r--r--media/libmedia/MediaProfiles.cpp10
-rw-r--r--media/libstagefright/rtsp/MyHandler.h2
-rw-r--r--nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java96
-rw-r--r--nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java16
-rw-r--r--nfc-extras/tests/Android.mk32
-rw-r--r--nfc-extras/tests/AndroidManifest.xml39
-rw-r--r--nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java117
-rw-r--r--opengl/include/EGL/eglext.h12
-rw-r--r--opengl/libs/EGL/eglApi.cpp2
-rw-r--r--opengl/libs/EGL/egl_cache.cpp40
-rw-r--r--opengl/libs/EGL/egl_cache.h8
-rw-r--r--opengl/specs/EGL_ANDROID_blob_cache.txt54
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_notification_open.pngbin1043 -> 1091 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_notification_open.pngbin788 -> 812 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_notification_open.pngbin1310 -> 1386 bytes
-rw-r--r--packages/SystemUI/res/layout-land/status_bar_recent_panel.xml36
-rw-r--r--packages/SystemUI/res/layout-port/status_bar_recent_panel.xml40
-rw-r--r--packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml36
-rw-r--r--packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml52
-rw-r--r--packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml47
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml40
-rw-r--r--packages/SystemUI/res/values-sw600dp/config.xml5
-rw-r--r--packages/SystemUI/res/values-sw600dp/dimens.xml10
-rw-r--r--packages/SystemUI/res/values/config.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/Choreographer.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java118
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java10
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java51
-rw-r--r--services/audioflinger/AudioFlinger.cpp39
-rw-r--r--services/audioflinger/AudioFlinger.h9
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java99
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java81
-rw-r--r--services/java/com/android/server/am/ActivityStack.java208
-rw-r--r--services/java/com/android/server/am/ContentProviderRecord.java4
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java23
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java6
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java55
-rw-r--r--telephony/java/com/android/internal/telephony/cat/CatService.java37
-rw-r--r--telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java16
-rw-r--r--telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java6
-rw-r--r--telephony/java/com/android/internal/telephony/cat/ValueParser.java25
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
new file mode 100644
index 000000000000..ebd6f8a1fe9c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/transportcontrol_bg.9.png b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
new file mode 100644
index 000000000000..d5a339fe51d1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
new file mode 100644
index 000000000000..b690a2a029dc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
Binary files differ
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"] />
&lt;/selector>
</pre>
@@ -690,8 +691,8 @@ child of a <code>&lt;selector&gt;</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>&lt;OMXAL/OpenMAXAL.h&gt;</code> and
+ <code>&lt;OMXAL/OpenMAXAL_Android.h&gt;</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/&lt;abi&gt;</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
index d697c2fdce63..cd9a54a904df 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
index 839c134a7598..5661eaf947f4 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png
index 4f8c98711c90..98455cf5b558 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png
Binary files differ
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;
}
/**