Merge "Doc change: New TTL error code." into jb-dev
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index 445aac63..bd9310c1 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -83,7 +83,7 @@
}
void setPos(int pos) {
- mPos = pos;
+ mPos = pos - mTextStart;
}
/**
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 26cc676..a760e41 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -434,8 +434,8 @@
<string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Mengizinkan apl memulai penyediaan CDMA. Apl berbahaya dapat memulai penyediaan CDMA yang tidak perlu."</string>
<string name="permlab_locationUpdates" msgid="7785408253364335740">"mengontrol pemberitahuan pembaruan lokasi"</string>
<string name="permdesc_locationUpdates" msgid="1120741557891438876">"Mengizinkan apl mengaktifkan/menonaktifkan pemberitahuan pembaruan lokasi dari radio. Tidak untuk digunakan oleh apl normal."</string>
- <string name="permlab_checkinProperties" msgid="7855259461268734914">"akses properti lapor masuk"</string>
- <string name="permdesc_checkinProperties" msgid="4024526968630194128">"Mengizinkan apl membaca/menulis akses ke properti yang diunggah oleh layanan lapor masuk. Tidak untuk digunakan oleh apl normal."</string>
+ <string name="permlab_checkinProperties" msgid="7855259461268734914">"akses properti check in"</string>
+ <string name="permdesc_checkinProperties" msgid="4024526968630194128">"Mengizinkan apl membaca/menulis akses ke properti yang diunggah oleh layanan check in. Tidak untuk digunakan oleh apl normal."</string>
<string name="permlab_bindGadget" msgid="776905339015863471">"pilih widget"</string>
<string name="permdesc_bindGadget" msgid="8261326938599049290">"Mengizinkan apl memberi tahu sistem tentang widget mana yang dapat digunakan oleh suatu apl. Apl dengan izin ini dapat memberikan akses ke data pribadi untuk apl lain. Tidak untuk digunakan oleh apl normal."</string>
<string name="permlab_modifyPhoneState" msgid="8423923777659292228">"ubah kondisi ponsel"</string>
diff --git a/data/fonts/AndroidEmoji.ttf b/data/fonts/AndroidEmoji.ttf
index 4c017d5..92bf047 100644
--- a/data/fonts/AndroidEmoji.ttf
+++ b/data/fonts/AndroidEmoji.ttf
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
index 25b6e7f..67da6ac 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
@@ -24,6 +24,7 @@
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
+import android.os.Environment;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
@@ -66,6 +67,9 @@
private int mTotalNotSeekable = 0;
private int mTotalMetaDataUpdate = 0;
+ //Test result output file
+ private static final String PLAYBACK_RESULT = "PlaybackTestResult.txt";
+
private void writeTestOutput(String filename, Writer output) throws Exception{
output.write("File Name: " + filename);
output.write(" Complete: " + CodecTest.onCompleteSuccess);
@@ -109,27 +113,19 @@
@LargeTest
public void testVideoPlayback() throws Exception {
String fileWithError = "Filename:\n";
- File playbackOutput = new File("/sdcard/PlaybackTestResult.txt");
+ File playbackOutput = new File(Environment.getExternalStorageDirectory(), PLAYBACK_RESULT);
Writer output = new BufferedWriter(new FileWriter(playbackOutput, true));
boolean testResult = true;
// load directory files
boolean onCompleteSuccess = false;
File dir = new File(MediaNames.MEDIA_SAMPLE_POOL);
-
- Instrumentation inst = getInstrumentation();
- Intent intent = new Intent();
-
- intent.setClass(getInstrumentation().getTargetContext(), MediaFrameworkTest.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
String[] children = dir.list();
if (children == null) {
Log.v("MediaPlayerApiTest:testMediaSamples", "dir is empty");
return;
} else {
for (int i = 0; i < children.length; i++) {
- Activity act = inst.startActivitySync(intent);
//Get filename of directory
String filename = children[i];
onCompleteSuccess =
@@ -141,8 +137,6 @@
testResult = false;
}
Thread.sleep(3000);
- //Call onCreat to recreate the surface
- act.finish();
//Write test result to an output file
writeTestOutput(filename,output);
//Get the summary
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
index f949e59..8ddb375 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png
index bbda474..57a3b99 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
index b97c664..71e1303 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png
index 222a826..1de0a3a 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight.png
index c9d96ec..202c8bc 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight_land.png
index 4c64b28..31bc09c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight.png
index 5f18ae3..bef6de3 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight_land.png
index d9df25c..406eeab 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight.png
index 2412a4e..75b5fbb 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight_land.png
index 114c778..a7a4ce3 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
index bf2553e..c44aafc 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
index 8df299e..05da6da 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
index 3a3044e..9746398 100644
--- a/telephony/java/com/android/internal/telephony/ApnContext.java
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -50,6 +50,8 @@
String mReason;
+ int mRetryCount;
+
/**
* user/app requested connection on this APN
*/
@@ -64,6 +66,7 @@
mApnType = apnType;
mState = DataConnectionTracker.State.IDLE;
setReason(Phone.REASON_DATA_ENABLED);
+ setRetryCount(0);
mDataEnabled = new AtomicBoolean(false);
mDependencyMet = new AtomicBoolean(true);
mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0);
@@ -182,6 +185,21 @@
return mReason;
}
+ public synchronized void setRetryCount(int retryCount) {
+ if (DBG) {
+ log("setRetryCount: " + retryCount);
+ }
+ mRetryCount = retryCount;
+ DataConnection dc = mDataConnection;
+ if (dc != null) {
+ dc.setRetryCount(retryCount);
+ }
+ }
+
+ public synchronized int getRetryCount() {
+ return mRetryCount;
+ }
+
public boolean isReady() {
return mDataEnabled.get() && mDependencyMet.get();
}
@@ -214,8 +232,8 @@
return "{mApnType=" + mApnType + " mState=" + getState() + " mWaitingApns=" + mWaitingApns +
" mWaitingApnsPermanentFailureCountDown=" + mWaitingApnsPermanentFailureCountDown +
" mApnSetting=" + mApnSetting + " mDataConnectionAc=" + mDataConnectionAc +
- " mReason=" + mReason + " mDataEnabled=" + mDataEnabled +
- " mDependencyMet=" + mDependencyMet + "}";
+ " mReason=" + mReason + " mRetryCount=" + mRetryCount +
+ " mDataEnabled=" + mDataEnabled + " mDependencyMet=" + mDependencyMet + "}";
}
protected void log(String s) {
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index cc4adfd..3f7e71e3 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -426,6 +426,14 @@
}
/**
+ * set retry manager retryCount
+ */
+ public void setRetryCount(int retryCount) {
+ if (DBG) log("setRetryCount: " + retryCount);
+ mRetryMgr.setRetryCount(retryCount);
+ }
+
+ /**
* @return retry manager retryTimer
*/
public int getRetryTimer() {
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 588515b..0dee7a1 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -303,7 +303,8 @@
new HashMap<String, Integer>();
/** Phone.APN_TYPE_* ===> ApnContext */
- protected ConcurrentHashMap<String, ApnContext> mApnContexts;
+ protected ConcurrentHashMap<String, ApnContext> mApnContexts =
+ new ConcurrentHashMap<String, ApnContext>();
/* Currently active APN */
protected ApnSetting mActiveApn;
@@ -1203,6 +1204,9 @@
}
protected void resetAllRetryCounts() {
+ for (ApnContext ac : mApnContexts.values()) {
+ ac.setRetryCount(0);
+ }
for (DataConnection dc : mDataConnections.values()) {
dc.resetRetryCount();
}
diff --git a/telephony/java/com/android/internal/telephony/RetryManager.java b/telephony/java/com/android/internal/telephony/RetryManager.java
index ae451b9..250d99e 100644
--- a/telephony/java/com/android/internal/telephony/RetryManager.java
+++ b/telephony/java/com/android/internal/telephony/RetryManager.java
@@ -73,7 +73,7 @@
* {@hide}
*/
public class RetryManager {
- static public final String LOG_TAG = "RetryManager";
+ static public final String LOG_TAG = "GSM";
static public final boolean DBG = true;
static public final boolean VDBG = false;
@@ -304,7 +304,6 @@
/**
* Set retry count to the specified value
- * and turns off retrying forever.
*/
public void setRetryCount(int count) {
mRetryCount = count;
@@ -316,11 +315,18 @@
mRetryCount = 0;
}
- mRetryForever = false;
if (DBG) log("setRetryCount: " + mRetryCount);
}
/**
+ * Set retry forever to the specified value
+ */
+ public void setRetryForever(boolean retryForever) {
+ mRetryForever = retryForever;
+ if (DBG) log("setRetryForever: " + mRetryForever);
+ }
+
+ /**
* Clear the data-retry counter
*/
public void resetRetryCount() {
@@ -399,6 +405,6 @@
}
private void log(String s) {
- Log.d(LOG_TAG, s);
+ Log.d(LOG_TAG, "[RM] " + s);
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 83fc9c1..6b863a7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -134,6 +134,8 @@
private static final String INTENT_RECONNECT_ALARM =
"com.android.internal.telephony.gprs-reconnect";
private static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "reconnect_alarm_extra_type";
+ private static final String INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT =
+ "reconnect_alaram_extra_retry_count";
private static final String INTENT_DATA_STALL_ALARM =
"com.android.internal.telephony.gprs-data-stall";
@@ -148,16 +150,23 @@
@Override
protected void onActionIntentReconnectAlarm(Intent intent) {
- if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
-
String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
int connectionId = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, -1);
+ int retryCount = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT, 0);
DataConnectionAc dcac= mDataConnectionAsyncChannels.get(connectionId);
+ if (DBG) {
+ log("onActionIntentReconnectAlarm: mState=" + mState + " reason=" + reason +
+ " connectionId=" + connectionId + " retryCount=" + retryCount);
+ }
+
if (dcac != null) {
for (ApnContext apnContext : dcac.getApnListSync()) {
+ apnContext.setDataConnectionAc(null);
+ apnContext.setDataConnection(null);
apnContext.setReason(reason);
+ apnContext.setRetryCount(retryCount);
if (apnContext.getState() == State.FAILED) {
apnContext.setState(State.IDLE);
}
@@ -205,7 +214,6 @@
p.getContext().getContentResolver().registerContentObserver(
Telephony.Carriers.CONTENT_URI, true, mApnObserver);
- mApnContexts = new ConcurrentHashMap<String, ApnContext>();
initApnContextsAndDataConnection();
broadcastMessenger();
}
@@ -672,10 +680,15 @@
break;
}
}
- configureRetry(dcac.dataConnection, hasDefault);
+ configureRetry(dcac.dataConnection, hasDefault, 0);
}
}
+ // Be sure retry counts for Apncontexts and DC's are sync'd.
+ // When DCT/ApnContexts are refactored and we cleanup retrying
+ // this won't be needed.
+ resetAllRetryCounts();
+
// Only check for default APN state
for (ApnContext apnContext : mApnContexts.values()) {
if (apnContext.getState() == State.FAILED) {
@@ -1076,7 +1089,8 @@
// configure retry count if no other Apn is using the same connection.
if (refCount == 0) {
- configureRetry(dc, apn.canHandleType(Phone.APN_TYPE_DEFAULT));
+ configureRetry(dc, apn.canHandleType(Phone.APN_TYPE_DEFAULT),
+ apnContext.getRetryCount());
}
apnContext.setDataConnectionAc(dcac);
apnContext.setDataConnection(dc);
@@ -1328,7 +1342,7 @@
startNetStatPoll();
startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
// reset reconnect timer
- apnContext.getDataConnection().resetRetryCount();
+ apnContext.setRetryCount(0);
}
// TODO: For multiple Active APNs not exactly sure how to do this.
@@ -1599,6 +1613,10 @@
loge("reconnectAfterFail: apnContext == null, impossible");
return;
}
+ if (DBG) {
+ log("reconnectAfterFail: lastFailCause=" + lastFailCauseCode +
+ " retryOverride=" + retryOverride + " apnContext=" + apnContext);
+ }
if ((apnContext.getState() == State.FAILED) &&
(apnContext.getDataConnection() != null)) {
if (!apnContext.getDataConnection().isRetryNeeded()) {
@@ -1614,7 +1632,7 @@
if (DBG) log("reconnectAfterFail: activate failed, Reregistering to network");
mReregisterOnReconnectFailure = true;
mPhone.getServiceStateTracker().reRegisterNetwork(null);
- apnContext.getDataConnection().resetRetryCount();
+ apnContext.setRetryCount(0);
return;
}
}
@@ -1625,6 +1643,11 @@
if (nextReconnectDelay < 0) {
nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
apnContext.getDataConnection().increaseRetryCount();
+ if (DBG) {
+ log("reconnectAfterFail: increaseRetryCount=" +
+ apnContext.getDataConnection().getRetryCount() +
+ " nextReconnectDelay=" + nextReconnectDelay);
+ }
}
startAlarmForReconnect(nextReconnectDelay, apnContext);
@@ -1641,16 +1664,11 @@
private void startAlarmForReconnect(int delay, ApnContext apnContext) {
- if (DBG) {
- log("Schedule alarm for reconnect: activate failed. Scheduling next attempt for "
- + (delay / 1000) + "s");
- }
-
DataConnectionAc dcac = apnContext.getDataConnectionAc();
if ((dcac == null) || (dcac.dataConnection == null)) {
// should not happen, but just in case.
- loge("null dcac or dc.");
+ loge("startAlarmForReconnect: null dcac or dc.");
return;
}
@@ -1659,12 +1677,29 @@
Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' +
dcac.dataConnection.getDataConnectionId());
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE,
- dcac.dataConnection.getDataConnectionId());
+ String reason = apnContext.getReason();
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
+ int connectionId = dcac.dataConnection.getDataConnectionId();
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, connectionId);
+
+ // TODO: Until a real fix is created, which probably entails pushing
+ // retires into the DC itself, this fix gets the retry count and
+ // puts it in the reconnect alarm. When the reconnect alarm fires
+ // onActionIntentReconnectAlarm is called which will use the value saved
+ // here and save it in the ApnContext and send the EVENT_CONNECT message
+ // which invokes setupData. Then setupData will use the value in the ApnContext
+ // and to tell the DC to set the retry count in the retry manager.
+ int retryCount = dcac.dataConnection.getRetryCount();
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT, retryCount);
+
+ if (DBG) {
+ log("startAlarmForReconnect: next attempt in " + (delay / 1000) + "s" +
+ " reason='" + reason + "' connectionId=" + connectionId +
+ " retryCount=" + retryCount);
+ }
PendingIntent alarmIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
- intent, 0);
+ intent, PendingIntent.FLAG_UPDATE_CURRENT);
dcac.setReconnectIntentSync(alarmIntent);
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + delay, alarmIntent);
@@ -1940,9 +1975,7 @@
// Make sure our reconnect delay starts at the initial value
// next time the radio comes on
- for (DataConnection dc : mDataConnections.values()) {
- dc.resetRetryCount();
- }
+ resetAllRetryCounts();
mReregisterOnReconnectFailure = false;
if (mPhone.getSimulatedRadioControl() != null) {
@@ -2285,7 +2318,11 @@
return conn;
}
- private void configureRetry(DataConnection dc, boolean forDefault) {
+ private void configureRetry(DataConnection dc, boolean forDefault, int retryCount) {
+ if (DBG) {
+ log("configureRetry: forDefault=" + forDefault + " retryCount=" + retryCount +
+ " dc=" + dc);
+ }
if (dc == null) return;
if (!dc.configureRetry(getReryConfig(forDefault))) {
@@ -2305,6 +2342,7 @@
}
}
}
+ dc.setRetryCount(retryCount);
}
private void destroyDataConnections() {
diff --git a/tools/layoutlib/bridge/src/android/util/LruCache.java b/tools/layoutlib/bridge/src/android/util/LruCache.java
new file mode 100644
index 0000000..5208606
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/util/LruCache.java
@@ -0,0 +1,391 @@
+/*
+ * 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 android.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * BEGIN LAYOUTLIB CHANGE
+ * This is a custom version that doesn't use the non standard LinkedHashMap#eldest.
+ * END LAYOUTLIB CHANGE
+ *
+ * A cache that holds strong references to a limited number of values. Each time
+ * a value is accessed, it is moved to the head of a queue. When a value is
+ * added to a full cache, the value at the end of that queue is evicted and may
+ * become eligible for garbage collection.
+ *
+ * <p>If your cached values hold resources that need to be explicitly released,
+ * override {@link #entryRemoved}.
+ *
+ * <p>If a cache miss should be computed on demand for the corresponding keys,
+ * override {@link #create}. This simplifies the calling code, allowing it to
+ * assume a value will always be returned, even when there's a cache miss.
+ *
+ * <p>By default, the cache size is measured in the number of entries. Override
+ * {@link #sizeOf} to size the cache in different units. For example, this cache
+ * is limited to 4MiB of bitmaps:
+ * <pre> {@code
+ * int cacheSize = 4 * 1024 * 1024; // 4MiB
+ * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
+ * protected int sizeOf(String key, Bitmap value) {
+ * return value.getByteCount();
+ * }
+ * }}</pre>
+ *
+ * <p>This class is thread-safe. Perform multiple cache operations atomically by
+ * synchronizing on the cache: <pre> {@code
+ * synchronized (cache) {
+ * if (cache.get(key) == null) {
+ * cache.put(key, value);
+ * }
+ * }}</pre>
+ *
+ * <p>This class does not allow null to be used as a key or value. A return
+ * value of null from {@link #get}, {@link #put} or {@link #remove} is
+ * unambiguous: the key was not in the cache.
+ *
+ * <p>This class appeared in Android 3.1 (Honeycomb MR1); it's available as part
+ * of <a href="http://developer.android.com/sdk/compatibility-library.html">Android's
+ * Support Package</a> for earlier releases.
+ */
+public class LruCache<K, V> {
+ private final LinkedHashMap<K, V> map;
+
+ /** Size of this cache in units. Not necessarily the number of elements. */
+ private int size;
+ private int maxSize;
+
+ private int putCount;
+ private int createCount;
+ private int evictionCount;
+ private int hitCount;
+ private int missCount;
+
+ /**
+ * @param maxSize for caches that do not override {@link #sizeOf}, this is
+ * the maximum number of entries in the cache. For all other caches,
+ * this is the maximum sum of the sizes of the entries in this cache.
+ */
+ public LruCache(int maxSize) {
+ if (maxSize <= 0) {
+ throw new IllegalArgumentException("maxSize <= 0");
+ }
+ this.maxSize = maxSize;
+ this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
+ }
+
+ /**
+ * Sets the size of the cache.
+ * @param maxSize The new maximum size.
+ *
+ * @hide
+ */
+ public void resize(int maxSize) {
+ if (maxSize <= 0) {
+ throw new IllegalArgumentException("maxSize <= 0");
+ }
+
+ synchronized (this) {
+ this.maxSize = maxSize;
+ }
+ trimToSize(maxSize);
+ }
+
+ /**
+ * Returns the value for {@code key} if it exists in the cache or can be
+ * created by {@code #create}. If a value was returned, it is moved to the
+ * head of the queue. This returns null if a value is not cached and cannot
+ * be created.
+ */
+ public final V get(K key) {
+ if (key == null) {
+ throw new NullPointerException("key == null");
+ }
+
+ V mapValue;
+ synchronized (this) {
+ mapValue = map.get(key);
+ if (mapValue != null) {
+ hitCount++;
+ return mapValue;
+ }
+ missCount++;
+ }
+
+ /*
+ * Attempt to create a value. This may take a long time, and the map
+ * may be different when create() returns. If a conflicting value was
+ * added to the map while create() was working, we leave that value in
+ * the map and release the created value.
+ */
+
+ V createdValue = create(key);
+ if (createdValue == null) {
+ return null;
+ }
+
+ synchronized (this) {
+ createCount++;
+ mapValue = map.put(key, createdValue);
+
+ if (mapValue != null) {
+ // There was a conflict so undo that last put
+ map.put(key, mapValue);
+ } else {
+ size += safeSizeOf(key, createdValue);
+ }
+ }
+
+ if (mapValue != null) {
+ entryRemoved(false, key, createdValue, mapValue);
+ return mapValue;
+ } else {
+ trimToSize(maxSize);
+ return createdValue;
+ }
+ }
+
+ /**
+ * Caches {@code value} for {@code key}. The value is moved to the head of
+ * the queue.
+ *
+ * @return the previous value mapped by {@code key}.
+ */
+ public final V put(K key, V value) {
+ if (key == null || value == null) {
+ throw new NullPointerException("key == null || value == null");
+ }
+
+ V previous;
+ synchronized (this) {
+ putCount++;
+ size += safeSizeOf(key, value);
+ previous = map.put(key, value);
+ if (previous != null) {
+ size -= safeSizeOf(key, previous);
+ }
+ }
+
+ if (previous != null) {
+ entryRemoved(false, key, previous, value);
+ }
+
+ trimToSize(maxSize);
+ return previous;
+ }
+
+ /**
+ * @param maxSize the maximum size of the cache before returning. May be -1
+ * to evict even 0-sized elements.
+ */
+ private void trimToSize(int maxSize) {
+ while (true) {
+ K key;
+ V value;
+ synchronized (this) {
+ if (size < 0 || (map.isEmpty() && size != 0)) {
+ throw new IllegalStateException(getClass().getName()
+ + ".sizeOf() is reporting inconsistent results!");
+ }
+
+ if (size <= maxSize) {
+ break;
+ }
+
+ // BEGIN LAYOUTLIB CHANGE
+ // get the last item in the linked list.
+ // This is not efficient, the goal here is to minimize the changes
+ // compared to the platform version.
+ Map.Entry<K, V> toEvict = null;
+ for (Map.Entry<K, V> entry : map.entrySet()) {
+ toEvict = entry;
+ }
+ // END LAYOUTLIB CHANGE
+
+ if (toEvict == null) {
+ break;
+ }
+
+ key = toEvict.getKey();
+ value = toEvict.getValue();
+ map.remove(key);
+ size -= safeSizeOf(key, value);
+ evictionCount++;
+ }
+
+ entryRemoved(true, key, value, null);
+ }
+ }
+
+ /**
+ * Removes the entry for {@code key} if it exists.
+ *
+ * @return the previous value mapped by {@code key}.
+ */
+ public final V remove(K key) {
+ if (key == null) {
+ throw new NullPointerException("key == null");
+ }
+
+ V previous;
+ synchronized (this) {
+ previous = map.remove(key);
+ if (previous != null) {
+ size -= safeSizeOf(key, previous);
+ }
+ }
+
+ if (previous != null) {
+ entryRemoved(false, key, previous, null);
+ }
+
+ return previous;
+ }
+
+ /**
+ * Called for entries that have been evicted or removed. This method is
+ * invoked when a value is evicted to make space, removed by a call to
+ * {@link #remove}, or replaced by a call to {@link #put}. The default
+ * implementation does nothing.
+ *
+ * <p>The method is called without synchronization: other threads may
+ * access the cache while this method is executing.
+ *
+ * @param evicted true if the entry is being removed to make space, false
+ * if the removal was caused by a {@link #put} or {@link #remove}.
+ * @param newValue the new value for {@code key}, if it exists. If non-null,
+ * this removal was caused by a {@link #put}. Otherwise it was caused by
+ * an eviction or a {@link #remove}.
+ */
+ protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}
+
+ /**
+ * Called after a cache miss to compute a value for the corresponding key.
+ * Returns the computed value or null if no value can be computed. The
+ * default implementation returns null.
+ *
+ * <p>The method is called without synchronization: other threads may
+ * access the cache while this method is executing.
+ *
+ * <p>If a value for {@code key} exists in the cache when this method
+ * returns, the created value will be released with {@link #entryRemoved}
+ * and discarded. This can occur when multiple threads request the same key
+ * at the same time (causing multiple values to be created), or when one
+ * thread calls {@link #put} while another is creating a value for the same
+ * key.
+ */
+ protected V create(K key) {
+ return null;
+ }
+
+ private int safeSizeOf(K key, V value) {
+ int result = sizeOf(key, value);
+ if (result < 0) {
+ throw new IllegalStateException("Negative size: " + key + "=" + value);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the size of the entry for {@code key} and {@code value} in
+ * user-defined units. The default implementation returns 1 so that size
+ * is the number of entries and max size is the maximum number of entries.
+ *
+ * <p>An entry's size must not change while it is in the cache.
+ */
+ protected int sizeOf(K key, V value) {
+ return 1;
+ }
+
+ /**
+ * Clear the cache, calling {@link #entryRemoved} on each removed entry.
+ */
+ public final void evictAll() {
+ trimToSize(-1); // -1 will evict 0-sized elements
+ }
+
+ /**
+ * For caches that do not override {@link #sizeOf}, this returns the number
+ * of entries in the cache. For all other caches, this returns the sum of
+ * the sizes of the entries in this cache.
+ */
+ public synchronized final int size() {
+ return size;
+ }
+
+ /**
+ * For caches that do not override {@link #sizeOf}, this returns the maximum
+ * number of entries in the cache. For all other caches, this returns the
+ * maximum sum of the sizes of the entries in this cache.
+ */
+ public synchronized final int maxSize() {
+ return maxSize;
+ }
+
+ /**
+ * Returns the number of times {@link #get} returned a value that was
+ * already present in the cache.
+ */
+ public synchronized final int hitCount() {
+ return hitCount;
+ }
+
+ /**
+ * Returns the number of times {@link #get} returned null or required a new
+ * value to be created.
+ */
+ public synchronized final int missCount() {
+ return missCount;
+ }
+
+ /**
+ * Returns the number of times {@link #create(Object)} returned a value.
+ */
+ public synchronized final int createCount() {
+ return createCount;
+ }
+
+ /**
+ * Returns the number of times {@link #put} was called.
+ */
+ public synchronized final int putCount() {
+ return putCount;
+ }
+
+ /**
+ * Returns the number of values that have been evicted.
+ */
+ public synchronized final int evictionCount() {
+ return evictionCount;
+ }
+
+ /**
+ * Returns a copy of the current contents of the cache, ordered from least
+ * recently accessed to most recently accessed.
+ */
+ public synchronized final Map<K, V> snapshot() {
+ return new LinkedHashMap<K, V>(map);
+ }
+
+ @Override public synchronized final String toString() {
+ int accesses = hitCount + missCount;
+ int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
+ return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
+ maxSize, hitCount, missCount, hitPercent);
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index f9e48e2b..3ae660d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -732,14 +732,16 @@
for (int i = 0 ; i < attrs.length ; i++) {
Pair<String, Boolean> attribute = attributes.get(i);
- // look for the value in the given style
- ResourceValue resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
- attribute.getSecond());
+ if (attribute != null) {
+ // look for the value in the given style
+ ResourceValue resValue = mRenderResources.findItemInStyle(style,
+ attribute.getFirst(), attribute.getSecond());
- if (resValue != null) {
- // resolve it to make sure there are no references left.
- ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
- mRenderResources.resolveResValue(resValue));
+ if (resValue != null) {
+ // resolve it to make sure there are no references left.
+ ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
+ mRenderResources.resolveResValue(resValue));
+ }
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 1817ab5..62c886b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -233,7 +233,7 @@
BridgeContext bridgeContext = (BridgeContext) mContext;
RenderResources res = bridgeContext.getRenderResources();
- ResourceValue value = res.findItemInTheme(themeEntryName);
+ ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/);
value = res.resolveResValue(value);
if (value instanceof StyleResourceValue == false) {
@@ -243,24 +243,27 @@
StyleResourceValue style = (StyleResourceValue) value;
// get the background
- ResourceValue backgroundValue = res.findItemInStyle(style, "background");
+ ResourceValue backgroundValue = res.findItemInStyle(style, "background",
+ true /*isFrameworkAttr*/);
backgroundValue = res.resolveResValue(backgroundValue);
if (backgroundValue != null) {
Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
if (d != null) {
- setBackgroundDrawable(d);
+ setBackground(d);
}
}
TextView textView = getStyleableTextView();
if (textView != null) {
// get the text style
- ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle");
+ ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle",
+ true /*isFrameworkAttr*/);
textStyleValue = res.resolveResValue(textStyleValue);
if (textStyleValue instanceof StyleResourceValue) {
StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
- ResourceValue textSize = res.findItemInStyle(textStyle, "textSize");
+ ResourceValue textSize = res.findItemInStyle(textStyle, "textSize",
+ true /*isFrameworkAttr*/);
textSize = res.resolveResValue(textSize);
if (textSize != null) {
@@ -273,7 +276,8 @@
}
- ResourceValue textColor = res.findItemInStyle(textStyle, "textColor");
+ ResourceValue textColor = res.findItemInStyle(textStyle, "textColor",
+ true /*isFrameworkAttr*/);
textColor = res.resolveResValue(textColor);
if (textColor != null) {
ColorStateList stateList = ResourceHelper.getColorStateList(
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 6840f46..e93b41d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -952,7 +952,8 @@
private void findBackground(RenderResources resources) {
if (getParams().isBgColorOverridden() == false) {
- mWindowBackground = resources.findItemInTheme("windowBackground");
+ mWindowBackground = resources.findItemInTheme("windowBackground",
+ true /*isFrameworkAttr*/);
if (mWindowBackground != null) {
mWindowBackground = resources.resolveResValue(mWindowBackground);
}
@@ -1003,7 +1004,8 @@
mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
// get value from the theme.
- ResourceValue value = resources.findItemInTheme("actionBarSize");
+ ResourceValue value = resources.findItemInTheme("actionBarSize",
+ true /*isFrameworkAttr*/);
// resolve it
value = resources.resolveResValue(value);
@@ -1028,7 +1030,8 @@
mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
// get value from the theme.
- ResourceValue value = resources.findItemInTheme("windowTitleSize");
+ ResourceValue value = resources.findItemInTheme("windowTitleSize",
+ true /*isFrameworkAttr*/);
// resolve it
value = resources.resolveResValue(value);
@@ -1068,11 +1071,20 @@
}
}
+ /**
+ * Looks for a attribute in the current theme. The attribute is in the android
+ * namespace.
+ *
+ * @param resources the render resources
+ * @param name the name of the attribute
+ * @param defaultValue the default value.
+ * @return the value of the attribute or the default one if not found.
+ */
private boolean getBooleanThemeValue(RenderResources resources,
String name, boolean defaultValue) {
// get the title bar flag from the current theme.
- ResourceValue value = resources.findItemInTheme(name);
+ ResourceValue value = resources.findItemInTheme(name, true /*isFrameworkAttr*/);
// because it may reference something else, we resolve it.
value = resources.resolveResValue(value);
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 79e02c8..5109810 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -116,7 +116,6 @@
"android.view.View#isInEditMode",
"android.view.ViewRootImpl#isInTouchMode",
"android.view.inputmethod.InputMethodManager#getInstance",
- "android.util.Log#println_native",
"com.android.internal.util.XmlUtils#convertValueToInt",
"com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
};
@@ -185,6 +184,7 @@
private final static String[] RENAMED_CLASSES =
new String[] {
"android.os.ServiceManager", "android.os._Original_ServiceManager",
+ "android.util.LruCache", "android.util._Original_LruCache",
"android.view.SurfaceView", "android.view._Original_SurfaceView",
"android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
"android.webkit.WebView", "android.webkit._Original_WebView",