diff options
1104 files changed, 7619 insertions, 5043 deletions
diff --git a/Android.mk b/Android.mk index 91850d5af79d..be8c25b714a1 100644 --- a/Android.mk +++ b/Android.mk @@ -381,7 +381,7 @@ framework_docs_LOCAL_DROIDDOC_OPTIONS := \ -since ./frameworks/base/api/11.xml 11 \ -since ./frameworks/base/api/12.xml 12 \ -since ./frameworks/base/api/13.xml 13 \ - -since ./frameworks/base/api/current.txt ICS \ + -since ./frameworks/base/api/14.txt 14 \ -werror -hide 113 \ -overview $(LOCAL_PATH)/core/java/overview.html @@ -473,7 +473,7 @@ web_docs_sample_code_flags := \ ## SDK version identifiers used in the published docs # major[.minor] version for current SDK. (full releases only) -framework_docs_SDK_VERSION:=3.2 +framework_docs_SDK_VERSION:=4.0 # release version (ie "Release x") (full releases only) framework_docs_SDK_REL_ID:=1 diff --git a/CleanSpec.mk b/CleanSpec.mk index d48904c30fdc..eb8471a74831 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -111,6 +111,9 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/wifi/java) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/wifi/java) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/Lohit_Hindi.ttf) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/DroidSans*) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/api/13.xml b/api/13.xml index 2bfa04ed8bc1..73995deca1ab 100644 --- a/api/13.xml +++ b/api/13.xml @@ -288451,7 +288451,7 @@ type="double" transient="false" volatile="false" - value="(-1.0 / 0.0)" + value="(-1.0/0.0)" static="true" final="true" deprecated="not deprecated" @@ -288462,7 +288462,7 @@ type="double" transient="false" volatile="false" - value="(0.0 / 0.0)" + value="(0.0/0.0)" static="true" final="true" deprecated="not deprecated" @@ -288473,7 +288473,7 @@ type="double" transient="false" volatile="false" - value="(1.0 / 0.0)" + value="(1.0/0.0)" static="true" final="true" deprecated="not deprecated" @@ -289154,7 +289154,7 @@ type="float" transient="false" volatile="false" - value="(-1.0f / 0.0f)" + value="(-1.0f/0.0f)" static="true" final="true" deprecated="not deprecated" @@ -289165,7 +289165,7 @@ type="float" transient="false" volatile="false" - value="(0.0f / 0.0f)" + value="(0.0f/0.0f)" static="true" final="true" deprecated="not deprecated" @@ -289176,7 +289176,7 @@ type="float" transient="false" volatile="false" - value="(1.0f / 0.0f)" + value="(1.0f/0.0f)" static="true" final="true" deprecated="not deprecated" diff --git a/api/14.txt b/api/14.txt index 45bb8823753f..9f2a6dfc3855 100644 --- a/api/14.txt +++ b/api/14.txt @@ -759,6 +759,7 @@ package android { field public static final int prompt = 16843131; // 0x101017b field public static final int propertyName = 16843489; // 0x10102e1 field public static final int protectionLevel = 16842761; // 0x1010009 + field public static final int publicKey = 16843686; // 0x10103a6 field public static final int queryActionMsg = 16843227; // 0x10101db field public static final int queryAfterZeroResults = 16843394; // 0x1010282 field public static final int queryHint = 16843608; // 0x1010358 @@ -4566,6 +4567,7 @@ package android.bluetooth { field public static final java.lang.String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE"; field public static final java.lang.String EXTRA_STATE = "android.bluetooth.profile.extra.STATE"; field public static final int HEADSET = 1; // 0x1 + field public static final int HEALTH = 3; // 0x3 field public static final int STATE_CONNECTED = 2; // 0x2 field public static final int STATE_CONNECTING = 1; // 0x1 field public static final int STATE_DISCONNECTED = 0; // 0x0 @@ -5454,6 +5456,7 @@ package android.content { field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH"; field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED"; field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL"; + field public static final java.lang.String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION"; field public static final java.lang.String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED"; field public static final java.lang.String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED"; field public static final java.lang.String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED"; @@ -6207,11 +6210,13 @@ package android.content.pm { method public abstract void setApplicationEnabledSetting(java.lang.String, int, int); method public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int); method public abstract void setInstallerPackageName(java.lang.String, java.lang.String); + method public abstract void verifyPendingInstall(int, int); field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0 field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2 field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3 field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1 field public static final int DONT_KILL_APP = 1; // 0x1 + field public static final java.lang.String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID"; field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency"; field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth"; field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera"; @@ -6273,6 +6278,8 @@ package android.content.pm { field public static final int SIGNATURE_NO_MATCH = -3; // 0xfffffffd field public static final int SIGNATURE_SECOND_NOT_SIGNED = -2; // 0xfffffffe field public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; // 0xfffffffc + field public static final int VERIFICATION_ALLOW = 1; // 0x1 + field public static final int VERIFICATION_REJECT = -1; // 0xffffffff } public static class PackageManager.NameNotFoundException extends android.util.AndroidException { @@ -19834,6 +19841,7 @@ package android.test.mock { method public void setApplicationEnabledSetting(java.lang.String, int, int); method public void setComponentEnabledSetting(android.content.ComponentName, int, int); method public void setInstallerPackageName(java.lang.String, java.lang.String); + method public void verifyPendingInstall(int, int); } public class MockResources extends android.content.res.Resources { diff --git a/api/current.txt b/api/current.txt index 45bb8823753f..9f2a6dfc3855 100644 --- a/api/current.txt +++ b/api/current.txt @@ -759,6 +759,7 @@ package android { field public static final int prompt = 16843131; // 0x101017b field public static final int propertyName = 16843489; // 0x10102e1 field public static final int protectionLevel = 16842761; // 0x1010009 + field public static final int publicKey = 16843686; // 0x10103a6 field public static final int queryActionMsg = 16843227; // 0x10101db field public static final int queryAfterZeroResults = 16843394; // 0x1010282 field public static final int queryHint = 16843608; // 0x1010358 @@ -4566,6 +4567,7 @@ package android.bluetooth { field public static final java.lang.String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE"; field public static final java.lang.String EXTRA_STATE = "android.bluetooth.profile.extra.STATE"; field public static final int HEADSET = 1; // 0x1 + field public static final int HEALTH = 3; // 0x3 field public static final int STATE_CONNECTED = 2; // 0x2 field public static final int STATE_CONNECTING = 1; // 0x1 field public static final int STATE_DISCONNECTED = 0; // 0x0 @@ -5454,6 +5456,7 @@ package android.content { field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH"; field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED"; field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL"; + field public static final java.lang.String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION"; field public static final java.lang.String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED"; field public static final java.lang.String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED"; field public static final java.lang.String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED"; @@ -6207,11 +6210,13 @@ package android.content.pm { method public abstract void setApplicationEnabledSetting(java.lang.String, int, int); method public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int); method public abstract void setInstallerPackageName(java.lang.String, java.lang.String); + method public abstract void verifyPendingInstall(int, int); field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0 field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2 field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3 field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1 field public static final int DONT_KILL_APP = 1; // 0x1 + field public static final java.lang.String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID"; field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency"; field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth"; field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera"; @@ -6273,6 +6278,8 @@ package android.content.pm { field public static final int SIGNATURE_NO_MATCH = -3; // 0xfffffffd field public static final int SIGNATURE_SECOND_NOT_SIGNED = -2; // 0xfffffffe field public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; // 0xfffffffc + field public static final int VERIFICATION_ALLOW = 1; // 0x1 + field public static final int VERIFICATION_REJECT = -1; // 0xffffffff } public static class PackageManager.NameNotFoundException extends android.util.AndroidException { @@ -19834,6 +19841,7 @@ package android.test.mock { method public void setApplicationEnabledSetting(java.lang.String, int, int); method public void setComponentEnabledSetting(android.content.ComponentName, int, int); method public void setInstallerPackageName(java.lang.String, java.lang.String); + method public void verifyPendingInstall(int, int); } public class MockResources extends android.content.res.Resources { diff --git a/cmds/ip-up-vpn/ip-up-vpn.c b/cmds/ip-up-vpn/ip-up-vpn.c index e9ee95d67680..0e6286f9279c 100644 --- a/cmds/ip-up-vpn/ip-up-vpn.c +++ b/cmds/ip-up-vpn/ip-up-vpn.c @@ -40,6 +40,7 @@ static const char *env(const char *name) { static int set_address(struct sockaddr *sa, const char *address) { sa->sa_family = AF_INET; + errno = EINVAL; return inet_pton(AF_INET, address, &((struct sockaddr_in *)sa)->sin_addr); } @@ -124,10 +125,11 @@ int main(int argc, char **argv) } /* Set the netmask. */ - if (!set_address(&ifr.ifr_netmask, env("INTERNAL_NETMASK4")) || - ioctl(s, SIOCSIFNETMASK, &ifr)) { - LOGE("Cannot set netmask: %s", strerror(errno)); - return 1; + if (set_address(&ifr.ifr_netmask, env("INTERNAL_NETMASK4"))) { + if (ioctl(s, SIOCSIFNETMASK, &ifr)) { + LOGE("Cannot set netmask: %s", strerror(errno)); + return 1; + } } /* TODO: Send few packets to trigger phase 2? */ diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp index 6fa66cf3524e..f547e019171c 100644 --- a/cmds/stagefright/sf2.cpp +++ b/cmds/stagefright/sf2.cpp @@ -46,7 +46,8 @@ struct Controller : public AHandler { mDecodeAudio(decodeAudio), mSurface(surface), mRenderToSurface(renderToSurface), - mCodec(new ACodec) { + mCodec(new ACodec), + mIsVorbis(false) { CHECK(!mDecodeAudio || mSurface == NULL); } @@ -85,6 +86,12 @@ protected: if (!strncasecmp(mDecodeAudio ? "audio/" : "video/", mime, 6)) { mSource = extractor->getTrack(i); + + if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { + mIsVorbis = true; + } else { + mIsVorbis = false; + } break; } } @@ -227,6 +234,7 @@ private: bool mRenderToSurface; sp<ACodec> mCodec; sp<MediaSource> mSource; + bool mIsVorbis; Vector<sp<ABuffer> > mCSD; size_t mCSDIndex; @@ -369,6 +377,20 @@ private: buffer->meta()->setInt32("csd", true); mCSD.push(buffer); + } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) { + sp<ABuffer> buffer = new ABuffer(size); + memcpy(buffer->data(), data, size); + + buffer->meta()->setInt32("csd", true); + mCSD.push(buffer); + + CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size)); + + buffer = new ABuffer(size); + memcpy(buffer->data(), data, size); + + buffer->meta()->setInt32("csd", true); + mCSD.push(buffer); } int32_t maxInputSize; @@ -423,10 +445,17 @@ private: } } - if (inBuffer->range_length() > sizeLeft) { + size_t sizeNeeded = inBuffer->range_length(); + if (mIsVorbis) { + // Vorbis data is suffixed with the number of + // valid samples on the page. + sizeNeeded += sizeof(int32_t); + } + + if (sizeNeeded > sizeLeft) { if (outBuffer->size() == 0) { LOGE("Unable to fit even a single input buffer of size %d.", - inBuffer->range_length()); + sizeNeeded); } CHECK_GT(outBuffer->size(), 0u); @@ -448,10 +477,22 @@ private: + inBuffer->range_offset(), inBuffer->range_length()); + if (mIsVorbis) { + int32_t numPageSamples; + if (!inBuffer->meta_data()->findInt32( + kKeyValidSamples, &numPageSamples)) { + numPageSamples = -1; + } + + memcpy(outBuffer->data() + + outBuffer->size() + inBuffer->range_length(), + &numPageSamples, sizeof(numPageSamples)); + } + outBuffer->setRange( - 0, outBuffer->size() + inBuffer->range_length()); + 0, outBuffer->size() + sizeNeeded); - sizeLeft -= inBuffer->range_length(); + sizeLeft -= sizeNeeded; inBuffer->release(); inBuffer = NULL; @@ -569,12 +610,16 @@ int main(int argc, char **argv) { CHECK(control->isValid()); SurfaceComposerClient::openGlobalTransaction(); - CHECK_EQ(control->setLayer(30000), (status_t)OK); + CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK); CHECK_EQ(control->show(), (status_t)OK); SurfaceComposerClient::closeGlobalTransaction(); surface = control->getSurface(); CHECK(surface != NULL); + + CHECK_EQ((status_t)OK, + native_window_api_connect( + surface.get(), NATIVE_WINDOW_API_MEDIA)); } sp<Controller> controller = @@ -589,6 +634,10 @@ int main(int argc, char **argv) { looper->unregisterHandler(controller->id()); if (!decodeAudio && useSurface) { + CHECK_EQ((status_t)OK, + native_window_api_disconnect( + surface.get(), NATIVE_WINDOW_API_MEDIA)); + composerClient->dispose(); } diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index 34f0a64f0b72..528d197dd0fb 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -133,6 +133,39 @@ static void displayAVCProfileLevelIfPossible(const sp<MetaData>& meta) { } } +static void dumpSource(const sp<MediaSource> &source, const String8 &filename) { + FILE *out = fopen(filename.string(), "wb"); + + CHECK_EQ((status_t)OK, source->start()); + + status_t err; + for (;;) { + MediaBuffer *mbuf; + err = source->read(&mbuf); + + if (err == INFO_FORMAT_CHANGED) { + continue; + } else if (err != OK) { + break; + } + + CHECK_EQ( + fwrite((const uint8_t *)mbuf->data() + mbuf->range_offset(), + 1, + mbuf->range_length(), + out), + (ssize_t)mbuf->range_length()); + + mbuf->release(); + mbuf = NULL; + } + + CHECK_EQ((status_t)OK, source->stop()); + + fclose(out); + out = NULL; +} + static void playSource(OMXClient *client, sp<MediaSource> &source) { sp<MetaData> meta = source->getFormat(); @@ -578,6 +611,7 @@ static void usage(const char *me) { "(video only)\n"); fprintf(stderr, " -S allocate buffers from a surface\n"); fprintf(stderr, " -T allocate buffers from a surface texture\n"); + fprintf(stderr, " -d(ump) filename (raw stream data to a file)\n"); } int main(int argc, char **argv) { @@ -590,6 +624,8 @@ int main(int argc, char **argv) { bool seekTest = false; bool useSurfaceAlloc = false; bool useSurfaceTexAlloc = false; + bool dumpStream = false; + String8 dumpStreamFilename; gNumRepetitions = 1; gMaxNumFrames = 0; gReproduceBug = -1; @@ -604,7 +640,7 @@ int main(int argc, char **argv) { sp<LiveSession> liveSession; int res; - while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxST")) >= 0) { + while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxSTd:")) >= 0) { switch (res) { case 'a': { @@ -612,6 +648,13 @@ int main(int argc, char **argv) { break; } + case 'd': + { + dumpStream = true; + dumpStreamFilename.setTo(optarg); + break; + } + case 'l': { listComponents = true; @@ -874,7 +917,7 @@ int main(int argc, char **argv) { CHECK(control->isValid()); SurfaceComposerClient::openGlobalTransaction(); - CHECK_EQ(control->setLayer(30000), (status_t)OK); + CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK); CHECK_EQ(control->show(), (status_t)OK); SurfaceComposerClient::closeGlobalTransaction(); @@ -886,6 +929,10 @@ int main(int argc, char **argv) { sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */); gSurface = new SurfaceTextureClient(texture); } + + CHECK_EQ((status_t)OK, + native_window_api_connect( + gSurface.get(), NATIVE_WINDOW_API_MEDIA)); } DataSource::RegisterDefaultSniffers(); @@ -1062,6 +1109,8 @@ int main(int argc, char **argv) { if (gWriteMP4) { writeSourcesToMP4(mediaSources, syncInfoPresent); + } else if (dumpStream) { + dumpSource(mediaSource, dumpStreamFilename); } else if (seekTest) { performSeekTest(mediaSource); } else { @@ -1077,6 +1126,10 @@ int main(int argc, char **argv) { } if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) { + CHECK_EQ((status_t)OK, + native_window_api_disconnect( + gSurface.get(), NATIVE_WINDOW_API_MEDIA)); + gSurface.clear(); if (useSurfaceAlloc) { diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp index b13236a3569c..2378345821c2 100644 --- a/cmds/stagefright/stream.cpp +++ b/cmds/stagefright/stream.cpp @@ -323,7 +323,7 @@ int main(int argc, char **argv) { CHECK(control->isValid()); SurfaceComposerClient::openGlobalTransaction(); - CHECK_EQ(control->setLayer(30000), (status_t)OK); + CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK); CHECK_EQ(control->show(), (status_t)OK); SurfaceComposerClient::closeGlobalTransaction(); diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 173da8d41e57..91def67e7aaf 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -1811,6 +1811,14 @@ public class AccountManagerService } protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + fout.println("Permission Denial: can't dump AccountsManager from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + synchronized (mCacheLock) { final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); diff --git a/core/java/android/accounts/ChooseAccountTypeActivity.java b/core/java/android/accounts/ChooseAccountTypeActivity.java index 5239e8c56fb0..448b2c0c49ae 100644 --- a/core/java/android/accounts/ChooseAccountTypeActivity.java +++ b/core/java/android/accounts/ChooseAccountTypeActivity.java @@ -33,7 +33,6 @@ import android.widget.ListView; import android.widget.TextView; import com.android.internal.R; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -43,7 +42,7 @@ import java.util.Set; /** * @hide */ -public class ChooseAccountTypeActivity extends Activity implements AccountManagerCallback<Bundle> { +public class ChooseAccountTypeActivity extends Activity { private static final String TAG = "AccountManager"; private HashMap<String, AuthInfo> mTypeToAuthenticatorInfo = new HashMap<String, AuthInfo>(); @@ -52,7 +51,6 @@ public class ChooseAccountTypeActivity extends Activity implements AccountManage @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.choose_account_type); // Read the validAccountTypes, if present, and add them to the setOfAllowableAccountTypes Set<String> setOfAllowableAccountTypes = null; @@ -90,10 +88,11 @@ public class ChooseAccountTypeActivity extends Activity implements AccountManage } if (mAuthenticatorInfosToDisplay.size() == 1) { - runAddAccountForAuthenticator(mAuthenticatorInfosToDisplay.get(0)); + setResultAndFinish(mAuthenticatorInfosToDisplay.get(0).desc.type); return; } + setContentView(R.layout.choose_account_type); // Setup the list ListView list = (ListView) findViewById(android.R.id.list); // Use an existing ListAdapter that will map an array of strings to TextViews @@ -103,11 +102,20 @@ public class ChooseAccountTypeActivity extends Activity implements AccountManage list.setTextFilterEnabled(false); list.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { - runAddAccountForAuthenticator(mAuthenticatorInfosToDisplay.get(position)); + setResultAndFinish(mAuthenticatorInfosToDisplay.get(position).desc.type); } }); } + private void setResultAndFinish(final String type) { + Bundle bundle = new Bundle(); + bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, type); + setResult(Activity.RESULT_OK, new Intent().putExtras(bundle)); + Log.d(TAG, "ChooseAccountTypeActivity.setResultAndFinish: " + + "selected account type " + type); + finish(); + } + private void buildTypeToAuthDescriptionMap() { for(AuthenticatorDescription desc : AccountManager.get(this).getAuthenticatorTypes()) { String name = null; @@ -136,42 +144,6 @@ public class ChooseAccountTypeActivity extends Activity implements AccountManage } } - protected void runAddAccountForAuthenticator(AuthInfo authInfo) { - Log.d(TAG, "selected account type " + authInfo.name); - final Bundle options = getIntent().getBundleExtra( - ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_OPTIONS_BUNDLE); - final String[] requiredFeatures = getIntent().getStringArrayExtra( - ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_REQUIRED_FEATURES_STRING_ARRAY); - final String authTokenType = getIntent().getStringExtra( - ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_AUTH_TOKEN_TYPE_STRING); - AccountManager.get(this).addAccount(authInfo.desc.type, authTokenType, requiredFeatures, - options, this, this, null /* Handler */); - } - - public void run(final AccountManagerFuture<Bundle> accountManagerFuture) { - try { - Bundle accountManagerResult = accountManagerFuture.getResult(); - Bundle bundle = new Bundle(); - bundle.putString(AccountManager.KEY_ACCOUNT_NAME, - accountManagerResult.getString(AccountManager.KEY_ACCOUNT_NAME)); - bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, - accountManagerResult.getString(AccountManager.KEY_ACCOUNT_TYPE)); - setResult(Activity.RESULT_OK, new Intent().putExtras(bundle)); - finish(); - return; - } catch (OperationCanceledException e) { - setResult(Activity.RESULT_CANCELED); - finish(); - return; - } catch (IOException e) { - } catch (AuthenticatorException e) { - } - Bundle bundle = new Bundle(); - bundle.putString(AccountManager.KEY_ERROR_MESSAGE, "error communicating with server"); - setResult(Activity.RESULT_OK, new Intent().putExtras(bundle)); - finish(); - } - private static class AuthInfo { final AuthenticatorDescription desc; final String name; diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java index 852c4dddf819..8cc200250ba3 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -36,6 +36,7 @@ import android.widget.ListView; import android.widget.TextView; import com.android.internal.R; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -44,7 +45,8 @@ import java.util.Set; /** * @hide */ -public class ChooseTypeAndAccountActivity extends Activity { +public class ChooseTypeAndAccountActivity extends Activity + implements AccountManagerCallback<Bundle> { private static final String TAG = "AccountManager"; /** @@ -211,10 +213,9 @@ public class ChooseTypeAndAccountActivity extends Activity { protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { if (resultCode == RESULT_OK && data != null) { - String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); String accountType = data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE); - if (accountName != null && accountType != null) { - setResultAndFinish(accountName, accountType); + if (accountType != null) { + runAddAccountForAuthenticator(accountType); return; } } @@ -223,6 +224,43 @@ public class ChooseTypeAndAccountActivity extends Activity { finish(); } + protected void runAddAccountForAuthenticator(String type) { + Log.d(TAG, "selected account type " + type); + final Bundle options = getIntent().getBundleExtra( + ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_OPTIONS_BUNDLE); + final String[] requiredFeatures = getIntent().getStringArrayExtra( + ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_REQUIRED_FEATURES_STRING_ARRAY); + final String authTokenType = getIntent().getStringExtra( + ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_AUTH_TOKEN_TYPE_STRING); + AccountManager.get(this).addAccount(type, authTokenType, requiredFeatures, + options, this, this, null /* Handler */); + } + + public void run(final AccountManagerFuture<Bundle> accountManagerFuture) { + try { + final Bundle accountManagerResult = accountManagerFuture.getResult(); + final String name = accountManagerResult.getString(AccountManager.KEY_ACCOUNT_NAME); + final String type = accountManagerResult.getString(AccountManager.KEY_ACCOUNT_TYPE); + if (name != null && type != null) { + final Bundle bundle = new Bundle(); + bundle.putString(AccountManager.KEY_ACCOUNT_NAME, name); + bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, type); + setResult(Activity.RESULT_OK, new Intent().putExtras(bundle)); + finish(); + return; + } + } catch (OperationCanceledException e) { + setResult(Activity.RESULT_CANCELED); + finish(); + return; + } catch (IOException e) { + } catch (AuthenticatorException e) { + } + Bundle bundle = new Bundle(); + bundle.putString(AccountManager.KEY_ERROR_MESSAGE, "error communicating with server"); + setResult(Activity.RESULT_OK, new Intent().putExtras(bundle)); + finish(); + } private Drawable getDrawableForType( final HashMap<String, AuthenticatorDescription> typeToAuthDescription, @@ -266,6 +304,7 @@ public class ChooseTypeAndAccountActivity extends Activity { private void startChooseAccountTypeActivity() { final Intent intent = new Intent(this, ChooseAccountTypeActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.putExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY, getIntent().getStringArrayExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY)); intent.putExtra(EXTRA_ADD_ACCOUNT_OPTIONS_BUNDLE, diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java index be00aa56b90f..51c6f3adbbb3 100644 --- a/core/java/android/app/ActionBar.java +++ b/core/java/android/app/ActionBar.java @@ -29,16 +29,29 @@ import android.view.Window; import android.widget.SpinnerAdapter; /** - * Acts as a replacement for the title bar in Activities. - * The action bar provides facilities for creating toolbar actions as well as - * methods of navigating the application. - * <p>By default, the action bar appears at the top of every activity, with the application icon on - * the left, followed by the activity title. Items from the activity's options menu are also - * accessible from the action bar.</p> + * A window feature at the top of the activity that may display the activity title, navigation + * modes, and other interactive items. + * <p>Beginning with Android 3.0 (API level 11), the action bar appears at the top of an + * activity's window when the activity uses the system's {@link + * android.R.style#Theme_Holo Holo} theme (or one of its descendant themes), which is the default. + * You may otherwise add the action bar by calling {@link + * android.view.Window#requestFeature requestFeature(FEATURE_ACTION_BAR)} or by declaring it in a + * custom theme with the {@link android.R.styleable#Theme_windowActionBar windowActionBar} property. + * <p>By default, the action bar shows the application icon on + * the left, followed by the activity title. If your activity has an options menu, you can make + * select items accessible directly from the action bar as "action items". You can also + * modify various characteristics of the action bar or remove it completely.</p> * <p>From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link * android.app.Activity#getActionBar getActionBar()}.</p> - * <p>For more information, read the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action + * <p>For information about how to use the action bar, including how to add action items, navigation + * modes and more, read the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action * Bar</a> developer guide.</p> + * <p>In some cases, the action bar may be overlayed by another bar that enables contextual actions, + * using an {@link android.view.ActionMode}. For example, when the user selects one or more items in + * your activity, you can enable an action mode that offers actions specific to the selected + * items, with a UI that temporarily replaces the action bar. Although the UI may occupy the + * same space, the {@link android.view.ActionMode} APIs are distinct and independent from those for + * {@link ActionBar}. */ public abstract class ActionBar { /** @@ -423,6 +436,7 @@ public abstract class ActionBar { * Set the ActionBar's split background. This will appear in * the split action bar containing menu-provided action buttons * on some devices and configurations. + * <p>You can enable split action bar with {@link android.R.attr#uiOptions} * * @param d Background drawable for the split bar */ @@ -460,13 +474,6 @@ public abstract class ActionBar { * </ul> * * @return The current navigation mode. - * - * @see #setStandardNavigationMode() - * @see #setStandardNavigationMode(CharSequence) - * @see #setStandardNavigationMode(CharSequence, CharSequence) - * @see #setDropdownNavigationMode(SpinnerAdapter) - * @see #setTabNavigationMode() - * @see #setCustomNavigationMode(View) */ public abstract int getNavigationMode(); @@ -498,7 +505,6 @@ public abstract class ActionBar { * @return A new Tab * * @see #addTab(Tab) - * @see #insertTab(Tab, int) */ public abstract Tab newTab(); @@ -606,7 +612,7 @@ public abstract class ActionBar { public abstract void show(); /** - * Hide the ActionBar if it is not currently showing. + * Hide the ActionBar if it is currently showing. * If the window hosting the ActionBar does not have the feature * {@link Window#FEATURE_ACTION_BAR_OVERLAY} it will resize application * content to fit the new space available. diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 77997796a8f7..b4471f096ad5 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1550,6 +1550,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + dismissKeyguardOnNextActivity(); + reply.writeNoException(); + return true; + } + } return super.onTransact(code, data, reply, flags); @@ -3504,5 +3511,15 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + public void dismissKeyguardOnNextActivity() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + private IBinder mRemote; } diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index bd42e3413ca7..8ed7481cddd1 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -954,9 +954,9 @@ final class ApplicationPackageManager extends PackageManager { } @Override - public void verifyPendingInstall(int id, boolean verified, String failureMessage) { + public void verifyPendingInstall(int id, int response) { try { - mPM.verifyPendingInstall(id, verified, failureMessage); + mPM.verifyPendingInstall(id, response); } catch (RemoteException e) { // Should never happen! } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 27dd6916af18..26813bf117df 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -372,6 +372,8 @@ public interface IActivityManager extends IInterface { public void showBootMessage(CharSequence msg, boolean always) throws RemoteException; + public void dismissKeyguardOnNextActivity() throws RemoteException; + /* * Private non-Binder interfaces */ @@ -602,4 +604,5 @@ public interface IActivityManager extends IInterface { int UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+135; int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136; int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137; + int DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+138; } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 254c98ff8cf0..ea5c3db86571 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -781,7 +781,7 @@ public final class BluetoothAdapter { * Get the current connection state of a profile. * This function can be used to check whether the local Bluetooth adapter * is connected to any remote device for a specific profile. - * Profile can be one of {@link BluetoothProfile#HEADSET}, + * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET}, * {@link BluetoothProfile#A2DP}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. @@ -1132,15 +1132,15 @@ public final class BluetoothAdapter { /** * Get the profile proxy object associated with the profile. * - * <p>Profile can be one of {@link BluetoothProfile#HEADSET} or + * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or * {@link BluetoothProfile#A2DP}. Clients must implements * {@link BluetoothProfile.ServiceListener} to get notified of * the connection status and to get the proxy object. * * @param context Context of the application * @param listener The service Listener for connection callbacks. - * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET} - * or {@link BluetoothProfile#A2DP}. + * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH}, + * {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}. * @return true on success, false on error */ public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, @@ -1172,7 +1172,7 @@ public final class BluetoothAdapter { * * <p> Clients should call this when they are no longer using * the proxy obtained from {@link #getProfileProxy}. - * Profile can be one of {@link BluetoothProfile#HEADSET} or + * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or * {@link BluetoothProfile#A2DP} * * @param profile diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 58b386838799..1920efa52f87 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -66,7 +66,6 @@ public interface BluetoothProfile { /** * Health Profile - * @hide */ public static final int HEALTH = 3; @@ -162,9 +161,9 @@ public interface BluetoothProfile { /** * Called to notify the client when the proxy object has been * connected to the service. - * @param profile - One of {@link #HEADSET} or + * @param profile - One of {@link #HEALTH}, {@link #HEADSET} or * {@link #A2DP} - * @param proxy - One of {@link BluetoothHeadset} or + * @param proxy - One of {@link BluetoothHealth}, {@link BluetoothHeadset} or * {@link BluetoothA2dp} */ public void onServiceConnected(int profile, BluetoothProfile proxy); @@ -172,7 +171,7 @@ public interface BluetoothProfile { /** * Called to notify the client that this proxy object has been * disconnected from the service. - * @param profile - One of {@link #HEADSET} or + * @param profile - One of {@link #HEALTH}, {@link #HEADSET} or * {@link #A2DP} */ public void onServiceDisconnected(int profile); diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index c7698bf17b72..f44d038a5fee 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1535,8 +1535,6 @@ public class Intent implements Parcelable, Cloneable { * <p class="note"> * This is a protected intent that can only be sent by the system. * </p> - * - * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION"; @@ -5579,24 +5577,35 @@ public class Intent implements Parcelable, Cloneable { @Override public String toString() { - StringBuilder b = new StringBuilder(128); + StringBuilder b = new StringBuilder(128); b.append("Intent { "); - toShortString(b, true, true); + toShortString(b, true, true, true); b.append(" }"); return b.toString(); } /** @hide */ - public String toShortString(boolean comp, boolean extras) { - StringBuilder b = new StringBuilder(128); - toShortString(b, comp, extras); + public String toInsecureString() { + StringBuilder b = new StringBuilder(128); + + b.append("Intent { "); + toShortString(b, false, true, true); + b.append(" }"); + return b.toString(); } /** @hide */ - public void toShortString(StringBuilder b, boolean comp, boolean extras) { + public String toShortString(boolean secure, boolean comp, boolean extras) { + StringBuilder b = new StringBuilder(128); + toShortString(b, secure, comp, extras); + return b.toString(); + } + + /** @hide */ + public void toShortString(StringBuilder b, boolean secure, boolean comp, boolean extras) { boolean first = true; if (mAction != null) { b.append("act=").append(mAction); @@ -5623,19 +5632,8 @@ public class Intent implements Parcelable, Cloneable { } first = false; b.append("dat="); - String scheme = mData.getScheme(); - if (scheme != null) { - if (scheme.equalsIgnoreCase("tel")) { - b.append("tel:xxx-xxx-xxxx"); - } else if (scheme.equalsIgnoreCase("sip")) { - b.append("sip:xxxxxxxxxx"); - } else if (scheme.equalsIgnoreCase("sms")) { - b.append("sms:xxx-xxx-xxxx"); - } else if (scheme.equalsIgnoreCase("smsto")) { - b.append("smsto:xxx-xxx-xxxx"); - } else { - b.append(mData); - } + if (secure) { + b.append(mData.toSafeString()); } else { b.append(mData); } diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index 684c4fed858e..127efa219308 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -16,22 +16,10 @@ package android.content; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.PowerManager; -import android.os.Process; -import android.os.RemoteException; -import android.os.SystemClock; -import android.os.SystemProperties; -import com.google.android.collect.Lists; -import com.google.android.collect.Maps; - import com.android.internal.R; import com.android.internal.util.ArrayUtils; +import com.google.android.collect.Lists; +import com.google.android.collect.Maps; import android.accounts.Account; import android.accounts.AccountManager; @@ -42,12 +30,23 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.RegisteredServicesCache; import android.content.pm.ProviderInfo; +import android.content.pm.RegisteredServicesCache; import android.content.pm.RegisteredServicesCacheListener; +import android.content.pm.ResolveInfo; import android.net.ConnectivityManager; import android.net.NetworkInfo; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.PowerManager; +import android.os.Process; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.SystemProperties; import android.os.WorkSource; import android.provider.Settings; import android.text.format.DateUtils; @@ -59,12 +58,15 @@ import android.util.Pair; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.concurrent.CountDownLatch; @@ -1006,9 +1008,8 @@ public class SyncManager implements OnAccountsUpdateListener { } protected void dump(FileDescriptor fd, PrintWriter pw) { - StringBuilder sb = new StringBuilder(); - dumpSyncState(pw, sb); - dumpSyncHistory(pw, sb); + dumpSyncState(pw); + dumpSyncHistory(pw); pw.println(); pw.println("SyncAdapters:"); @@ -1023,7 +1024,7 @@ public class SyncManager implements OnAccountsUpdateListener { return tobj.format("%Y-%m-%d %H:%M:%S"); } - protected void dumpSyncState(PrintWriter pw, StringBuilder sb) { + protected void dumpSyncState(PrintWriter pw) { pw.print("data connected: "); pw.println(mDataConnectionIsConnected); pw.print("memory low: "); pw.println(mStorageIsLow); @@ -1055,7 +1056,7 @@ public class SyncManager implements OnAccountsUpdateListener { } pw.print("notification info: "); - sb.setLength(0); + final StringBuilder sb = new StringBuilder(); mSyncHandler.mSyncNotificationInfo.toString(sb); pw.println(sb.toString()); @@ -1204,7 +1205,197 @@ public class SyncManager implements OnAccountsUpdateListener { pw.println(")"); } - protected void dumpSyncHistory(PrintWriter pw, StringBuilder sb) { + protected void dumpSyncHistory(PrintWriter pw) { + dumpRecentHistory(pw); + dumpDayStatistics(pw); + } + + private void dumpRecentHistory(PrintWriter pw) { + final ArrayList<SyncStorageEngine.SyncHistoryItem> items + = mSyncStorageEngine.getSyncHistory(); + if (items != null && items.size() > 0) { + final Map<String, AuthoritySyncStats> authorityMap = Maps.newHashMap(); + long totalElapsedTime = 0; + long totalTimes = 0; + final int N = items.size(); + + int maxAuthority = 0; + int maxAccount = 0; + for (SyncStorageEngine.SyncHistoryItem item : items) { + SyncStorageEngine.AuthorityInfo authority + = mSyncStorageEngine.getAuthority(item.authorityId); + final String authorityName; + final String accountKey; + if (authority != null) { + authorityName = authority.authority; + accountKey = authority.account.name + "/" + authority.account.type; + } else { + authorityName = "Unknown"; + accountKey = "Unknown"; + } + + int length = authorityName.length(); + if (length > maxAuthority) { + maxAuthority = length; + } + length = accountKey.length(); + if (length > maxAccount) { + maxAccount = length; + } + + final long elapsedTime = item.elapsedTime; + totalElapsedTime += elapsedTime; + totalTimes++; + AuthoritySyncStats authoritySyncStats = authorityMap.get(authorityName); + if (authoritySyncStats == null) { + authoritySyncStats = new AuthoritySyncStats(authorityName); + authorityMap.put(authorityName, authoritySyncStats); + } + authoritySyncStats.elapsedTime += elapsedTime; + authoritySyncStats.times++; + final Map<String, AccountSyncStats> accountMap = authoritySyncStats.accountMap; + AccountSyncStats accountSyncStats = accountMap.get(accountKey); + if (accountSyncStats == null) { + accountSyncStats = new AccountSyncStats(accountKey); + accountMap.put(accountKey, accountSyncStats); + } + accountSyncStats.elapsedTime += elapsedTime; + accountSyncStats.times++; + + } + + pw.println(); + pw.printf("Detailed Statistics (Recent history): %d (# of times) %ds (sync time)\n", + totalTimes, totalElapsedTime / 1000); + + final List<AuthoritySyncStats> sortedAuthorities = + new ArrayList<AuthoritySyncStats>(authorityMap.values()); + Collections.sort(sortedAuthorities, new Comparator<AuthoritySyncStats>() { + @Override + public int compare(AuthoritySyncStats lhs, AuthoritySyncStats rhs) { + // reverse order + int compare = Integer.compare(rhs.times, lhs.times); + if (compare == 0) { + compare = Long.compare(rhs.elapsedTime, lhs.elapsedTime); + } + return compare; + } + }); + + final int maxLength = Math.max(maxAuthority, maxAccount + 3); + final int padLength = 2 + 2 + maxLength + 2 + 10 + 11; + final char chars[] = new char[padLength]; + Arrays.fill(chars, '-'); + final String separator = new String(chars); + + final String authorityFormat = String.format(" %%-%ds: %%-9s %%-11s\n", maxLength + 2); + final String accountFormat = String.format(" %%-%ds: %%-9s %%-11s\n", maxLength); + + pw.println(separator); + for (AuthoritySyncStats authoritySyncStats : sortedAuthorities) { + String name = authoritySyncStats.name; + long elapsedTime; + int times; + String timeStr; + String timesStr; + + elapsedTime = authoritySyncStats.elapsedTime; + times = authoritySyncStats.times; + timeStr = String.format("%d/%d%%", + elapsedTime / 1000, + elapsedTime * 100 / totalElapsedTime); + timesStr = String.format("%d/%d%%", + times, + times * 100 / totalTimes); + pw.printf(authorityFormat, name, timesStr, timeStr); + + if (authoritySyncStats.accountMap.size() > 1) { + final List<AccountSyncStats> sortedAccounts = + new ArrayList<AccountSyncStats>( + authoritySyncStats.accountMap.values()); + Collections.sort(sortedAccounts, new Comparator<AccountSyncStats>() { + @Override + public int compare(AccountSyncStats lhs, AccountSyncStats rhs) { + // reverse order + int compare = Integer.compare(rhs.times, lhs.times); + if (compare == 0) { + compare = Long.compare(rhs.elapsedTime, lhs.elapsedTime); + } + return compare; + } + }); + for (AccountSyncStats stats: sortedAccounts) { + elapsedTime = stats.elapsedTime; + times = stats.times; + timeStr = String.format("%d/%d%%", + elapsedTime / 1000, + elapsedTime * 100 / totalElapsedTime); + timesStr = String.format("%d/%d%%", + times, + times * 100 / totalTimes); + pw.printf(accountFormat, stats.name, timesStr, timeStr); + } + } + pw.println(separator); + } + + pw.println(); + pw.println("Recent Sync History"); + final String format = " %-" + maxAccount + "s %s\n"; + String lastAuthorityName = null; + String lastAccountKey = null; + long lastEventTime = 0; + for (int i = 0; i < N; i++) { + SyncStorageEngine.SyncHistoryItem item = items.get(i); + SyncStorageEngine.AuthorityInfo authority + = mSyncStorageEngine.getAuthority(item.authorityId); + final String authorityName; + final String accountKey; + if (authority != null) { + authorityName = authority.authority; + accountKey = authority.account.name + "/" + authority.account.type; + } else { + authorityName = "Unknown"; + accountKey = "Unknown"; + } + final long elapsedTime = item.elapsedTime; + final Time time = new Time(); + final long eventTime = item.eventTime; + time.set(eventTime); + + pw.printf(" #%-3d: %s %8s %5.1fs", + i + 1, + formatTime(eventTime), + SyncStorageEngine.SOURCES[item.source], + ((float) elapsedTime) / 1000); + if (authorityName.equals(lastAuthorityName) && accountKey.equals(lastAccountKey)) { + final long span = (lastEventTime - eventTime) / 1000; + pw.printf(" %02d:%02d\n", span / 60, span % 60); + } else { + pw.printf(format, accountKey, authorityName); + } + + lastAuthorityName = authorityName; + lastAccountKey = accountKey; + lastEventTime = eventTime; + + if (item.event != SyncStorageEngine.EVENT_STOP + || item.upstreamActivity != 0 + || item.downstreamActivity != 0) { + pw.printf(" event=%d upstreamActivity=%d downstreamActivity=%d\n", + item.event, + item.upstreamActivity, + item.downstreamActivity); + } + if (item.mesg != null + && !SyncStorageEngine.MESG_SUCCESS.equals(item.mesg)) { + pw.printf(" mesg=%s\n", item.mesg); + } + } + } + } + + private void dumpDayStatistics(PrintWriter pw) { SyncStorageEngine.DayStats dses[] = mSyncStorageEngine.getDayStatistics(); if (dses != null && dses[0] != null) { pw.println(); @@ -1254,47 +1445,26 @@ public class SyncManager implements OnAccountsUpdateListener { } } } + } - ArrayList<SyncStorageEngine.SyncHistoryItem> items - = mSyncStorageEngine.getSyncHistory(); - if (items != null && items.size() > 0) { - pw.println(); - pw.println("Recent Sync History"); - final int N = items.size(); - for (int i=0; i<N; i++) { - SyncStorageEngine.SyncHistoryItem item = items.get(i); - SyncStorageEngine.AuthorityInfo authority - = mSyncStorageEngine.getAuthority(item.authorityId); - pw.print(" #"); pw.print(i+1); pw.print(": "); - if (authority != null) { - pw.print(authority.account.name); - pw.print(":"); - pw.print(authority.account.type); - pw.print(" "); - pw.print(authority.authority); - } else { - pw.print("<no account>"); - } - Time time = new Time(); - time.set(item.eventTime); - pw.print(" "); pw.print(SyncStorageEngine.SOURCES[item.source]); - pw.print(" @ "); - pw.print(formatTime(item.eventTime)); - pw.print(" for "); - dumpTimeSec(pw, item.elapsedTime); - pw.println(); - if (item.event != SyncStorageEngine.EVENT_STOP - || item.upstreamActivity !=0 - || item.downstreamActivity != 0) { - pw.print(" event="); pw.print(item.event); - pw.print(" upstreamActivity="); pw.print(item.upstreamActivity); - pw.print(" downstreamActivity="); pw.println(item.downstreamActivity); - } - if (item.mesg != null - && !SyncStorageEngine.MESG_SUCCESS.equals(item.mesg)) { - pw.print(" mesg="); pw.println(item.mesg); - } - } + private static class AuthoritySyncStats { + String name; + long elapsedTime; + int times; + Map<String, AccountSyncStats> accountMap = Maps.newHashMap(); + + private AuthoritySyncStats(String name) { + this.name = name; + } + } + + private static class AccountSyncStats { + String name; + long elapsedTime; + int times; + + private AccountSyncStats(String name) { + this.name = name; } } diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index bba329dd441e..0e6694deef2c 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -442,7 +442,11 @@ public class ActivityInfo extends ComponentInfo public int uiOptions = 0; /** - * Flag for use with uiOptions. + * Flag for use with {@link #uiOptions}. + * Indicates that the action bar should put all action items in a separate bar when + * the screen is narrow. + * <p>This value corresponds to "splitActionBarWhenNarrow" for the {@link #uiOptions} XML + * attribute. */ public static final int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 1; diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 5e6e7686c174..a3bcc287e021 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -359,7 +359,7 @@ interface IPackageManager { int flags, in String installerPackageName, in Uri verificationURI, in ManifestDigest manifestDigest); - void verifyPendingInstall(int id, boolean verified, in String message); + void verifyPendingInstall(int id, int verificationCode); VerifierDeviceIdentity getVerifierDeviceIdentity(); } diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java index da97fde006ef..962594440e8f 100644 --- a/core/java/android/content/pm/PackageInfoLite.java +++ b/core/java/android/content/pm/PackageInfoLite.java @@ -41,6 +41,8 @@ public class PackageInfoLite implements Parcelable { public int recommendedInstallLocation; public int installLocation; + public VerifierInfo[] verifiers; + public PackageInfoLite() { } @@ -58,6 +60,13 @@ public class PackageInfoLite implements Parcelable { dest.writeString(packageName); dest.writeInt(recommendedInstallLocation); dest.writeInt(installLocation); + + if (verifiers == null || verifiers.length == 0) { + dest.writeInt(0); + } else { + dest.writeInt(verifiers.length); + dest.writeTypedArray(verifiers, parcelableFlags); + } } public static final Parcelable.Creator<PackageInfoLite> CREATOR @@ -75,5 +84,13 @@ public class PackageInfoLite implements Parcelable { packageName = source.readString(); recommendedInstallLocation = source.readInt(); installLocation = source.readInt(); + + final int verifiersLength = source.readInt(); + if (verifiersLength == 0) { + verifiers = new VerifierInfo[0]; + } else { + verifiers = new VerifierInfo[verifiersLength]; + source.readTypedArray(verifiers, VerifierInfo.CREATOR); + } } } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index dcb677617f2e..7a7e4f4b54ab 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -725,7 +725,32 @@ public abstract class PackageManager { public static final int MOVE_EXTERNAL_MEDIA = 0x00000002; /** + * Usable by the required verifier as the {@code verificationCode} argument + * for {@link PackageManager#verifyPendingInstall} to indicate that it will + * allow the installation to proceed without any of the optional verifiers + * needing to vote. + * + * @hide + */ + public static final int VERIFICATION_ALLOW_WITHOUT_SUFFICIENT = 2; + + /** + * Used as the {@code verificationCode} argument for + * {@link PackageManager#verifyPendingInstall} to indicate that the calling + * package verifier allows the installation to proceed. + */ + public static final int VERIFICATION_ALLOW = 1; + + /** + * Used as the {@code verificationCode} argument for + * {@link PackageManager#verifyPendingInstall} to indicate the calling + * package verifier does not vote to allow the installation to proceed. + */ + public static final int VERIFICATION_REJECT = -1; + + /** * Range of IDs allocated for a user. + * * @hide */ public static final int PER_USER_RANGE = 100000; @@ -1045,9 +1070,7 @@ public abstract class PackageManager { /** * Extra field name for the ID of a package pending verification. Passed to * a package verifier and is used to call back to - * {@link PackageManager#verifyPendingInstall(int, boolean)} - * - * @hide + * {@link PackageManager#verifyPendingInstall(int, int)} */ public static final String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID"; @@ -2156,16 +2179,17 @@ public abstract class PackageManager { /** * Allows a package listening to the * {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION package verification - * broadcast} to respond to the package manager. + * broadcast} to respond to the package manager. The response must include + * the {@code verificationCode} which is one of + * {@link PackageManager#VERIFICATION_ALLOW} or + * {@link PackageManager#VERIFICATION_REJECT}. * * @param id pending package identifier as passed via the * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra - * @param verified whether the package was verified as valid - * @param failureMessage if verification was false, this is the error - * message that may be shown to the user - * @hide + * @param verificationCode either {@link PackageManager#VERIFICATION_ALLOW} + * or {@link PackageManager#VERIFICATION_REJECT}. */ - public abstract void verifyPendingInstall(int id, boolean verified, String failureMessage); + public abstract void verifyPendingInstall(int id, int verificationCode); /** * Change the installer associated with a given package. There are limitations @@ -2513,6 +2537,7 @@ public abstract class PackageManager { * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the * application's enabled state is based on the original information in * the manifest as found in {@link ComponentInfo}. + * @throws IllegalArgumentException if the named package does not exist. */ public abstract int getApplicationEnabledSetting(String packageName); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index e7b844c4808b..c30675b6a36d 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -28,7 +28,9 @@ import android.os.Build; import android.os.Bundle; import android.os.PatternMatcher; import android.util.AttributeSet; +import android.util.Base64; import android.util.DisplayMetrics; +import android.util.Log; import android.util.Slog; import android.util.TypedValue; import com.android.internal.util.XmlUtils; @@ -40,11 +42,18 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; +import java.security.spec.EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; +import java.util.List; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -150,12 +159,14 @@ public class PackageParser { * @hide */ public static class PackageLite { - public String packageName; - public int installLocation; - public String mScanPath; - public PackageLite(String packageName, int installLocation) { + public final String packageName; + public final int installLocation; + public final VerifierInfo[] verifiers; + + public PackageLite(String packageName, int installLocation, List<VerifierInfo> verifiers) { this.packageName = packageName; this.installLocation = installLocation; + this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); } } @@ -619,8 +630,9 @@ public class PackageParser { * @return PackageLite object with package information or null on failure. */ public static PackageLite parsePackageLite(String packageFilePath, int flags) { - XmlResourceParser parser = null; AssetManager assmgr = null; + final XmlResourceParser parser; + final Resources res; try { assmgr = new AssetManager(); assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -631,6 +643,9 @@ public class PackageParser { return null; } + final DisplayMetrics metrics = new DisplayMetrics(); + metrics.setToDefaults(); + res = new Resources(assmgr, metrics, null); parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); } catch (Exception e) { if (assmgr != null) assmgr.close(); @@ -638,11 +653,12 @@ public class PackageParser { + packageFilePath, e); return null; } - AttributeSet attrs = parser; - String errors[] = new String[1]; + + final AttributeSet attrs = parser; + final String errors[] = new String[1]; PackageLite packageLite = null; try { - packageLite = parsePackageLite(parser, attrs, flags, errors); + packageLite = parsePackageLite(res, parser, attrs, flags, errors); } catch (IOException e) { Slog.w(TAG, packageFilePath, e); } catch (XmlPullParserException e) { @@ -719,9 +735,9 @@ public class PackageParser { return pkgName.intern(); } - private static PackageLite parsePackageLite(XmlPullParser parser, - AttributeSet attrs, int flags, String[] outError) - throws IOException, XmlPullParserException { + private static PackageLite parsePackageLite(Resources res, XmlPullParser parser, + AttributeSet attrs, int flags, String[] outError) throws IOException, + XmlPullParserException { int type; while ((type = parser.next()) != XmlPullParser.START_TAG @@ -759,7 +775,26 @@ public class PackageParser { break; } } - return new PackageLite(pkgName.intern(), installLocation); + + // Only search the tree when the tag is directly below <manifest> + final int searchDepth = parser.getDepth() + 1; + + final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) { + final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags, outError); + if (verifier != null) { + verifiers.add(verifier); + } + } + } + + return new PackageLite(pkgName.intern(), installLocation, verifiers); } /** @@ -2691,6 +2726,63 @@ public class PackageParser { return data; } + private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser, + AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException, + IOException { + final TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestPackageVerifier); + + final String packageName = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPackageVerifier_name); + + final String encodedPublicKey = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey); + + sa.recycle(); + + if (packageName == null || packageName.length() == 0) { + Slog.i(TAG, "verifier package name was null; skipping"); + return null; + } else if (encodedPublicKey == null) { + Slog.i(TAG, "verifier " + packageName + " public key was null; skipping"); + } + + EncodedKeySpec keySpec; + try { + final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT); + keySpec = new X509EncodedKeySpec(encoded); + } catch (IllegalArgumentException e) { + Slog.i(TAG, "Could not parse verifier " + packageName + " public key; invalid Base64"); + return null; + } + + /* First try the key as an RSA key. */ + try { + final KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + final PublicKey publicKey = keyFactory.generatePublic(keySpec); + return new VerifierInfo(packageName, publicKey); + } catch (NoSuchAlgorithmException e) { + Log.wtf(TAG, "Could not parse public key because RSA isn't included in build"); + return null; + } catch (InvalidKeySpecException e) { + // Not a RSA public key. + } + + /* Now try it as a DSA key. */ + try { + final KeyFactory keyFactory = KeyFactory.getInstance("DSA"); + final PublicKey publicKey = keyFactory.generatePublic(keySpec); + return new VerifierInfo(packageName, publicKey); + } catch (NoSuchAlgorithmException e) { + Log.wtf(TAG, "Could not parse public key because DSA isn't included in build"); + return null; + } catch (InvalidKeySpecException e) { + // Not a DSA public key. + } + + return null; + } + private static final String ANDROID_RESOURCES = "http://schemas.android.com/apk/res/android"; diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java index c6aefb87c723..9c9340d0ef00 100644 --- a/core/java/android/content/pm/Signature.java +++ b/core/java/android/content/pm/Signature.java @@ -19,7 +19,12 @@ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; +import java.io.ByteArrayInputStream; import java.lang.ref.SoftReference; +import java.security.PublicKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.util.Arrays; /** @@ -135,6 +140,20 @@ public class Signature implements Parcelable { return bytes; } + /** + * Returns the public key for this signature. + * + * @throws CertificateException when Signature isn't a valid X.509 + * certificate; shouldn't happen. + * @hide + */ + public PublicKey getPublicKey() throws CertificateException { + final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + final ByteArrayInputStream bais = new ByteArrayInputStream(mSignature); + final Certificate cert = certFactory.generateCertificate(bais); + return cert.getPublicKey(); + } + @Override public boolean equals(Object obj) { try { diff --git a/core/java/android/content/pm/VerifierInfo.aidl b/core/java/android/content/pm/VerifierInfo.aidl new file mode 100644 index 000000000000..7702d387d3f0 --- /dev/null +++ b/core/java/android/content/pm/VerifierInfo.aidl @@ -0,0 +1,19 @@ +/* + * 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. + */ + +package android.content.pm; + +parcelable VerifierInfo; diff --git a/core/java/android/content/pm/VerifierInfo.java b/core/java/android/content/pm/VerifierInfo.java new file mode 100644 index 000000000000..0a2b2832d319 --- /dev/null +++ b/core/java/android/content/pm/VerifierInfo.java @@ -0,0 +1,83 @@ +/* + * 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.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.security.PublicKey; + +/** + * Contains information about a package verifier as used by + * {@code PackageManagerService} during package verification. + * + * @hide + */ +public class VerifierInfo implements Parcelable { + /** Package name of the verifier. */ + public final String packageName; + + /** Signatures used to sign the package verifier's package. */ + public final PublicKey publicKey; + + /** + * Creates an object that represents a verifier info object. + * + * @param packageName the package name in Java-style. Must not be {@code + * null} or empty. + * @param publicKey the public key for the signer encoded in Base64. Must + * not be {@code null} or empty. + * @throws IllegalArgumentException if either argument is null or empty. + */ + public VerifierInfo(String packageName, PublicKey publicKey) { + if (packageName == null || packageName.length() == 0) { + throw new IllegalArgumentException("packageName must not be null or empty"); + } else if (publicKey == null) { + throw new IllegalArgumentException("publicKey must not be null"); + } + + this.packageName = packageName; + this.publicKey = publicKey; + } + + private VerifierInfo(Parcel source) { + packageName = source.readString(); + publicKey = (PublicKey) source.readSerializable(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(packageName); + dest.writeSerializable(publicKey); + } + + public static final Parcelable.Creator<VerifierInfo> CREATOR + = new Parcelable.Creator<VerifierInfo>() { + public VerifierInfo createFromParcel(Parcel source) { + return new VerifierInfo(source); + } + + public VerifierInfo[] newArray(int size) { + return new VerifierInfo[size]; + } + }; +}
\ No newline at end of file diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 58f7869f5e95..e40de266606c 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -480,6 +480,12 @@ public class Camera { public final void stopPreview() { _stopPreview(); mFaceDetectionRunning = false; + + mShutterCallback = null; + mRawImageCallback = null; + mPostviewCallback = null; + mJpegCallback = null; + mAutoFocusCallback = null; } private native final void _stopPreview(); @@ -766,15 +772,8 @@ public class Camera { * onAutoFocus will be called immediately with a fake value of * <code>success</code> set to <code>true</code>. * - * The auto-focus routine may lock auto-exposure and auto-white balance - * after it completes. To check for the state of these locks, use the - * {@link android.hardware.Camera.Parameters#getAutoExposureLock()} and - * {@link android.hardware.Camera.Parameters#getAutoWhiteBalanceLock()} - * methods. If such locking is undesirable, use - * {@link android.hardware.Camera.Parameters#setAutoExposureLock(boolean)} - * and - * {@link android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean)} - * to release the locks. + * The auto-focus routine does not lock auto-exposure and auto-white + * balance after it completes. * * @param success true if focus was successful, false if otherwise * @param camera the Camera service object @@ -805,16 +804,10 @@ public class Camera { * {@link android.hardware.Camera.Parameters#FLASH_MODE_OFF}, flash may be * fired during auto-focus, depending on the driver and camera hardware.<p> * - * The auto-focus routine may lock auto-exposure and auto-white balance - * after it completes. To check for the state of these locks, use the - * {@link android.hardware.Camera.Parameters#getAutoExposureLock()} and - * {@link android.hardware.Camera.Parameters#getAutoWhiteBalanceLock()} - * methods after the {@link AutoFocusCallback#onAutoFocus(boolean, Camera)} - * callback is invoked. If such locking is undesirable, use - * {@link android.hardware.Camera.Parameters#setAutoExposureLock(boolean)} - * and - * {@link android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean)} - * to release the locks. + * Auto-exposure lock {@link android.hardware.Camera.Parameters#getAutoExposureLock()} + * and auto-white balance locks {@link android.hardware.Camera.Parameters#getAutoWhiteBalanceLock()} + * do not change during and after autofocus. But auto-focus routine may stop + * auto-exposure and auto-white balance transiently during focusing. * * @param cb the callback to run * @see #cancelAutoFocus() @@ -834,13 +827,7 @@ public class Camera { * this function will return the focus position to the default. * If the camera does not support auto-focus, this is a no-op. * - * Canceling auto-focus will return the auto-exposure lock and auto-white - * balance lock to their state before {@link #autoFocus(AutoFocusCallback)} - * was called. - * * @see #autoFocus(Camera.AutoFocusCallback) - * @see android.hardware.Camera.Parameters#setAutoExposureLock(boolean) - * @see android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean) */ public final void cancelAutoFocus() { @@ -2778,13 +2765,12 @@ public class Camera { * * <p>Stopping preview with {@link #stopPreview()}, or triggering still * image capture with {@link #takePicture(Camera.ShutterCallback, - * Camera.PictureCallback, Camera.PictureCallback)}, will automatically - * set the lock to false. However, the lock can be re-enabled before - * preview is re-started to keep the same AE parameters.</p> + * Camera.PictureCallback, Camera.PictureCallback)}, will not change the + * lock.</p> * - * <p>Exposure compensation, in conjunction with re-enabling the AE and - * AWB locks after each still capture, can be used to capture an - * exposure-bracketed burst of images, for example.</p> + * <p>Exposure compensation, auto-exposure lock, and auto-white balance + * lock can be used to capture an exposure-bracketed burst of images, + * for example.</p> * * <p>Auto-exposure state, including the lock state, will not be * maintained after camera {@link #release()} is called. Locking @@ -2793,14 +2779,6 @@ public class Camera { * run at all, and may result in severely over- or under-exposed * images.</p> * - * <p>The driver may also independently lock auto-exposure after - * auto-focus completes. If this is undesirable, be sure to always set - * the auto-exposure lock to false after the - * {@link AutoFocusCallback#onAutoFocus(boolean, Camera)} callback is - * received. The {@link #getAutoExposureLock()} method can be used after - * the callback to determine if the camera has locked auto-exposure - * independently.</p> - * * @param toggle new state of the auto-exposure lock. True means that * auto-exposure is locked, false means that the auto-exposure * routine is free to run normally. @@ -2817,11 +2795,7 @@ public class Camera { * {@link #setAutoExposureLock} for details about the lock. * * @return State of the auto-exposure lock. Returns true if - * auto-exposure is currently locked, and false otherwise. The - * auto-exposure lock may be independently enabled by the camera - * subsystem when auto-focus has completed. This method can be - * used after the {@link AutoFocusCallback#onAutoFocus(boolean, - * Camera)} callback to determine if the camera has locked AE. + * auto-exposure is currently locked, and false otherwise. * * @see #setAutoExposureLock(boolean) * @@ -2859,29 +2833,20 @@ public class Camera { * * <p>Stopping preview with {@link #stopPreview()}, or triggering still * image capture with {@link #takePicture(Camera.ShutterCallback, - * Camera.PictureCallback, Camera.PictureCallback)}, will automatically - * set the lock to false. However, the lock can be re-enabled before - * preview is re-started to keep the same white balance parameters.</p> + * Camera.PictureCallback, Camera.PictureCallback)}, will not change the + * the lock.</p> * * <p> Changing the white balance mode with {@link #setWhiteBalance} * will release the auto-white balance lock if it is set.</p> * - * <p>Exposure compensation, in conjunction with re-enabling the AE and - * AWB locks after each still capture, can be used to capture an - * exposure-bracketed burst of images, for example. Auto-white balance - * state, including the lock state, will not be maintained after camera - * {@link #release()} is called. Locking auto-white balance after - * {@link #open()} but before the first call to {@link #startPreview()} - * will not allow the auto-white balance routine to run at all, and may - * result in severely incorrect color in captured images.</p> - * - * <p>The driver may also independently lock auto-white balance after - * auto-focus completes. If this is undesirable, be sure to always set - * the auto-white balance lock to false after the - * {@link AutoFocusCallback#onAutoFocus(boolean, Camera)} callback is - * received. The {@link #getAutoWhiteBalanceLock()} method can be used - * after the callback to determine if the camera has locked auto-white - * balance independently.</p> + * <p>Exposure compensation, AE lock, and AWB lock can be used to + * capture an exposure-bracketed burst of images, for example. + * Auto-white balance state, including the lock state, will not be + * maintained after camera {@link #release()} is called. Locking + * auto-white balance after {@link #open()} but before the first call to + * {@link #startPreview()} will not allow the auto-white balance routine + * to run at all, and may result in severely incorrect color in captured + * images.</p> * * @param toggle new state of the auto-white balance lock. True means * that auto-white balance is locked, false means that the @@ -2902,11 +2867,7 @@ public class Camera { * * @return State of the auto-white balance lock. Returns true if * auto-white balance is currently locked, and false - * otherwise. The auto-white balance lock may be independently - * enabled by the camera subsystem when auto-focus has - * completed. This method can be used after the - * {@link AutoFocusCallback#onAutoFocus(boolean, Camera)} - * callback to determine if the camera has locked AWB. + * otherwise. * * @see #setAutoWhiteBalanceLock(boolean) * diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java index 10386f84671d..4fe54c0aa4dd 100644 --- a/core/java/android/inputmethodservice/Keyboard.java +++ b/core/java/android/inputmethodservice/Keyboard.java @@ -144,6 +144,8 @@ public class Keyboard { /** Number of key widths from current touch point to search for nearest keys. */ private static float SEARCH_DISTANCE = 1.8f; + private ArrayList<Row> rows = new ArrayList<Row>(); + /** * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate. * Some of the key size defaults can be overridden per row from what the {@link Keyboard} @@ -164,6 +166,9 @@ public class Keyboard { public int defaultHorizontalGap; /** Vertical gap following this row. */ public int verticalGap; + + ArrayList<Key> mKeys = new ArrayList<Key>(); + /** * Edge flags for this row of keys. Possible values that can be assigned are * {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM} @@ -256,7 +261,7 @@ public class Keyboard { public CharSequence text; /** Popup characters */ public CharSequence popupCharacters; - + /** * Flags that specify the anchoring to edges of the keyboard for detecting touch events * that are just out of the boundary of the key. This is a bit mask of @@ -596,11 +601,44 @@ public class Keyboard { column++; x += key.width + key.gap; mKeys.add(key); + row.mKeys.add(key); if (x > mTotalWidth) { mTotalWidth = x; } } - mTotalHeight = y + mDefaultHeight; + mTotalHeight = y + mDefaultHeight; + rows.add(row); + } + + final void resize(int newWidth, int newHeight) { + int numRows = rows.size(); + for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) { + Row row = rows.get(rowIndex); + int numKeys = row.mKeys.size(); + int totalGap = 0; + int totalWidth = 0; + for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) { + Key key = row.mKeys.get(keyIndex); + if (keyIndex > 0) { + totalGap += key.gap; + } + totalWidth += key.width; + } + if (totalGap + totalWidth > newWidth) { + int x = 0; + float scaleFactor = (float)(newWidth - totalGap) / totalWidth; + for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) { + Key key = row.mKeys.get(keyIndex); + key.width *= scaleFactor; + key.x = x; + x += key.width + key.gap; + } + } + } + mTotalWidth = newWidth; + // TODO: This does not adjust the vertical placement according to the new size. + // The main problem in the previous code was horizontal placement/size, but we should + // also recalculate the vertical sizes/positions when we get this resize call. } public List<Key> getKeys() { @@ -749,7 +787,7 @@ public class Keyboard { Row currentRow = null; Resources res = context.getResources(); boolean skipRow = false; - + try { int event; while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { @@ -759,6 +797,7 @@ public class Keyboard { inRow = true; x = 0; currentRow = createRowFromXml(res, parser); + rows.add(currentRow); skipRow = currentRow.mode != 0 && currentRow.mode != mKeyboardMode; if (skipRow) { skipToEndOfRow(parser); @@ -781,6 +820,7 @@ public class Keyboard { } else if (key.codes[0] == KEYCODE_ALT) { mModifierKeys.add(key); } + currentRow.mKeys.add(key); } else if (TAG_KEYBOARD.equals(tag)) { parseKeyboardAttributes(res, parser); } diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java index 05444f628ffe..1119c1eb1b31 100644 --- a/core/java/android/inputmethodservice/KeyboardView.java +++ b/core/java/android/inputmethodservice/KeyboardView.java @@ -376,6 +376,7 @@ public class KeyboardView extends View implements View.OnClickListener { initGestureDetector(); } + private void initGestureDetector() { mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() { @Override @@ -615,6 +616,9 @@ public class KeyboardView extends View implements View.OnClickListener { @Override public void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); + if (mKeyboard != null) { + mKeyboard.resize(w, h); + } // Release the buffer, if any and it will be reallocated on the next draw mBuffer = null; } diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java index 3e27b0defc07..3291e6b5c917 100644 --- a/core/java/android/net/DnsPinger.java +++ b/core/java/android/net/DnsPinger.java @@ -53,7 +53,7 @@ import java.util.concurrent.atomic.AtomicInteger; public final class DnsPinger extends Handler { private static final boolean V = true; - private static final int RECEIVE_POLL_INTERVAL_MS = 30; + private static final int RECEIVE_POLL_INTERVAL_MS = 200; private static final int DNS_PORT = 53; /** Short socket timeout so we don't block one any 'receive' call */ @@ -70,6 +70,9 @@ public final class DnsPinger extends Handler { private final ArrayList<InetAddress> mDefaultDns; private String TAG; + //Invalidates old dns requests upon a cancel + private AtomicInteger mCurrentToken = new AtomicInteger(); + private static final int BASE = Protocol.BASE_DNS_PINGER; /** @@ -102,6 +105,17 @@ public final class DnsPinger extends Handler { long start = SystemClock.elapsedRealtime(); } + /* Message argument for ACTION_PING_DNS */ + private class DnsArg { + InetAddress dns; + int seq; + + DnsArg(InetAddress d, int s) { + dns = d; + seq = s; + } + } + public DnsPinger(Context context, String TAG, Looper looper, Handler target, int connectionType) { super(looper); @@ -122,9 +136,13 @@ public final class DnsPinger extends Handler { public void handleMessage(Message msg) { switch (msg.what) { case ACTION_PING_DNS: + DnsArg dnsArg = (DnsArg) msg.obj; + if (dnsArg.seq != mCurrentToken.get()) { + break; + } try { ActivePing newActivePing = new ActivePing(); - InetAddress dnsAddress = (InetAddress) msg.obj; + InetAddress dnsAddress = dnsArg.dns; newActivePing.internalId = msg.arg1; newActivePing.timeout = msg.arg2; newActivePing.socket = new DatagramSocket(); @@ -248,11 +266,13 @@ public final class DnsPinger extends Handler { */ public int pingDnsAsync(InetAddress dns, int timeout, int delay) { int id = sCounter.incrementAndGet(); - sendMessageDelayed(obtainMessage(ACTION_PING_DNS, id, timeout, dns), delay); + sendMessageDelayed(obtainMessage(ACTION_PING_DNS, id, timeout, + new DnsArg(dns, mCurrentToken.get())), delay); return id; } public void cancelPings() { + mCurrentToken.incrementAndGet(); obtainMessage(ACTION_CANCEL_ALL_PINGS).sendToTarget(); } diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index bcf6239afbca..62bb9657f796 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -56,7 +56,7 @@ import java.io.PrintWriter; public class MobileDataStateTracker implements NetworkStateTracker { private static final String TAG = "MobileDataStateTracker"; - private static final boolean DBG = true; + private static final boolean DBG = false; private static final boolean VDBG = false; private Phone.DataState mMobileDataState; diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index a5cdf70325ee..a6635bee205a 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -270,6 +270,11 @@ public class NetworkStatsHistory implements Parcelable { || entry.operations < 0) { throw new IllegalArgumentException("tried recording negative data"); } + if (entry.rxBytes == 0 && entry.rxPackets == 0 && entry.txBytes == 0 && entry.txPackets == 0 + && entry.operations == 0) { + // nothing to record; skip + return; + } // create any buckets needed by this range ensureBuckets(start, end); diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index cd4902308b72..418b82fdeaa2 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -19,14 +19,15 @@ package android.net; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIMAX; -import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkIdentity.scrubSubscriberId; import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G; import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G; import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G; import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN; import static android.telephony.TelephonyManager.getNetworkClass; +import static com.android.internal.util.ArrayUtils.contains; +import android.content.res.Resources; import android.os.Parcel; import android.os.Parcelable; @@ -52,6 +53,16 @@ public class NetworkTemplate implements Parcelable { public static final int MATCH_ETHERNET = 5; /** + * Set of {@link NetworkInfo#getType()} that reflect data usage. + */ + private static final int[] DATA_USAGE_NETWORK_TYPES; + + static { + DATA_USAGE_NETWORK_TYPES = Resources.getSystem().getIntArray( + com.android.internal.R.array.config_data_usage_network_types); + } + + /** * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style * networks together. Only uses statistics for requested IMSI. */ @@ -151,7 +162,7 @@ public class NetworkTemplate implements Parcelable { } /** - * Test if this network matches the given template and IMSI. + * Test if given {@link NetworkIdentity} matches this template. */ public boolean matches(NetworkIdentity ident) { switch (mMatchRule) { @@ -171,23 +182,25 @@ public class NetworkTemplate implements Parcelable { } /** - * Check if mobile network with matching IMSI. Also matches - * {@link #TYPE_WIMAX}. + * Check if mobile network with matching IMSI. */ private boolean matchesMobile(NetworkIdentity ident) { - if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) { - return true; - } else if (ident.mType == TYPE_WIMAX) { + if (ident.mType == TYPE_WIMAX) { + // TODO: consider matching against WiMAX subscriber identity return true; + } else { + return (contains(DATA_USAGE_NETWORK_TYPES, ident.mType) + && Objects.equal(mSubscriberId, ident.mSubscriberId)); } - return false; } /** * Check if mobile network classified 3G or lower with matching IMSI. */ private boolean matchesMobile3gLower(NetworkIdentity ident) { - if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) { + if (ident.mType == TYPE_WIMAX) { + return false; + } else if (matchesMobile(ident)) { switch (getNetworkClass(ident.mSubType)) { case NETWORK_CLASS_UNKNOWN: case NETWORK_CLASS_2_G: @@ -199,17 +212,17 @@ public class NetworkTemplate implements Parcelable { } /** - * Check if mobile network classified 4G with matching IMSI. Also matches - * {@link #TYPE_WIMAX}. + * Check if mobile network classified 4G with matching IMSI. */ private boolean matchesMobile4g(NetworkIdentity ident) { - if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) { + if (ident.mType == TYPE_WIMAX) { + // TODO: consider matching against WiMAX subscriber identity + return true; + } else if (matchesMobile(ident)) { switch (getNetworkClass(ident.mSubType)) { case NETWORK_CLASS_4_G: return true; } - } else if (ident.mType == TYPE_WIMAX) { - return true; } return false; } diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java index 44dbec1ba508..cd799da9d7d2 100644 --- a/core/java/android/net/ProxyProperties.java +++ b/core/java/android/net/ProxyProperties.java @@ -137,6 +137,8 @@ public class ProxyProperties implements Parcelable { if (mExclusionList != null) { sb.append(" xl=").append(mExclusionList); } + } else { + sb.append("[ProxyProperties.mHost == null]"); } return sb.toString(); } diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index 2c875c82e780..9d28effe27b1 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -353,6 +353,48 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { public abstract String toString(); /** + * Return a string representation of the URI that is safe to print + * to logs and other places where PII should be avoided. + * @hide + */ + public String toSafeString() { + String scheme = getScheme(); + String ssp = getSchemeSpecificPart(); + if (scheme != null) { + if (scheme.equalsIgnoreCase("tel") || scheme.equalsIgnoreCase("sip") + || scheme.equalsIgnoreCase("sms") || scheme.equalsIgnoreCase("smsto") + || scheme.equalsIgnoreCase("mailto")) { + StringBuilder builder = new StringBuilder(64); + builder.append(scheme); + builder.append(':'); + if (ssp != null) { + for (int i=0; i<ssp.length(); i++) { + char c = ssp.charAt(i); + if (c == '-' || c == '@' || c == '.') { + builder.append(c); + } else { + builder.append('x'); + } + } + } + return builder.toString(); + } + } + // Not a sensitive scheme, but let's still be conservative about + // the data we include -- only the ssp, not the query params or + // fragment, because those can often have sensitive info. + StringBuilder builder = new StringBuilder(64); + if (scheme != null) { + builder.append(scheme); + builder.append(':'); + } + if (ssp != null) { + builder.append(ssp); + } + return builder.toString(); + } + + /** * Constructs a new builder, copying the attributes from this Uri. */ public abstract Builder buildUpon(); diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index e392bca671ee..fe0106dc52c4 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -208,7 +208,9 @@ public final class NfcAdapter { final NfcActivityManager mNfcActivityManager; /** - * @see {@link #setNdefPushMessageCallback} + * A callback to be invoked when the system successfully delivers your {@link NdefMessage} + * to another device. + * @see #setOnNdefPushCompleteCallback */ public interface OnNdefPushCompleteCallback { /** @@ -217,13 +219,21 @@ public final class NfcAdapter { * <p>This callback is usually made on a binder thread (not the UI thread). * * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set - * @see {@link #setNdefPushMessageCallback} + * @see #setNdefPushMessageCallback */ public void onNdefPushComplete(NfcEvent event); } /** - * @see {@link #setCeateNdefMessageCallback} + * A callback to be invoked when another NFC device capable of NDEF push (Android Beam) + * is within range. + * <p>Implement this interface and pass it to {@link + * NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} in order to create an + * {@link NdefMessage} at the moment that another device is within range for NFC. Using this + * callback allows you to create a message with data that might vary based on the + * content currently visible to the user. Alternatively, you can call {@link + * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the + * same data. */ public interface CreateNdefMessageCallback { /** @@ -507,13 +517,15 @@ public final class NfcAdapter { * <p>Pass a null NDEF message to disable foreground NDEF push in the * specified activities. * - * <p>One or more activities must be specified. + * <p>At least one activity must be specified, and usually only one is necessary. * * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. * * @param message NDEF message to push over NFC, or null to disable - * @param activity an activity to enable for NDEF push (at least one is required) - * @param activities zero or more additional activities to enable for NDEF Push + * @param activity an activity in which NDEF push should be enabled to share the provided + * NDEF message + * @param activities optional additional activities that should also enable NDEF push with + * the provided NDEF message */ public void setNdefPushMessage(NdefMessage message, Activity activity, Activity ... activities) { @@ -544,13 +556,15 @@ public final class NfcAdapter { * <p>Pass a null callback to disable the callback in the * specified activities. * - * <p>One or more activities must be specified. + * <p>At least one activity must be specified, and usually only one is necessary. * * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. * * @param callback callback, or null to disable - * @param activity an activity to enable for NDEF push (at least one is required) - * @param activities zero or more additional activities to enable for NDEF Push + * @param activity an activity in which NDEF push should be enabled to share an NDEF message + * that's retrieved from the provided callback + * @param activities optional additional activities that should also enable NDEF push using + * the provided callback */ public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, Activity ... activities) { diff --git a/core/java/android/nfc/NfcEvent.java b/core/java/android/nfc/NfcEvent.java index b00d8b755b03..860700a80f02 100644 --- a/core/java/android/nfc/NfcEvent.java +++ b/core/java/android/nfc/NfcEvent.java @@ -29,8 +29,8 @@ package android.nfc; * in the callback) because it allows new fields to be added without breaking * API compatibility. * - * @see {@link NfcAdapter.OnNdefPushCompleteCallback#onNdefPushComplete} - * @see {@link NfcAdapter.CreateNdefMessageCallback#createNdefMessage} + * @see NfcAdapter.OnNdefPushCompleteCallback#onNdefPushComplete + * @see NfcAdapter.CreateNdefMessageCallback#createNdefMessage */ public final class NfcEvent { /** diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 66373fe242e6..be87946b4d56 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -79,6 +79,16 @@ interface INetworkManagementService void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable); /** + * Disable IPv6 on an interface + */ + void disableIpv6(String iface); + + /** + * Enable IPv6 on an interface + */ + void enableIpv6(String iface); + + /** * Retrieves the network routes currently configured on the specified * interface */ diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java index 45e3a4ccf984..8b9945925da2 100644 --- a/core/java/android/preference/PreferenceScreen.java +++ b/core/java/android/preference/PreferenceScreen.java @@ -25,6 +25,8 @@ import android.os.Parcelable; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; +import android.view.Window; +import android.widget.AbsListView; import android.widget.Adapter; import android.widget.AdapterView; import android.widget.ListAdapter; @@ -156,13 +158,13 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi // Set the title bar if title is available, else no title bar final CharSequence title = getTitle(); - Dialog dialog = mDialog = new Dialog(context, TextUtils.isEmpty(title) - ? com.android.internal.R.style.Theme_NoTitleBar - : com.android.internal.R.style.Theme); - dialog.setContentView(mListView); - if (!TextUtils.isEmpty(title)) { + Dialog dialog = mDialog = new Dialog(context, context.getThemeResId()); + if (TextUtils.isEmpty(title)) { + dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); + } else { dialog.setTitle(title); } + dialog.setContentView(mListView); dialog.setOnDismissListener(this); if (state != null) { dialog.onRestoreInstanceState(state); @@ -189,9 +191,13 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi } public void onItemClick(AdapterView parent, View view, int position, long id) { + // If the list has headers, subtract them from the index. + if (parent instanceof ListView) { + position -= ((ListView) parent).getHeaderViewsCount(); + } Object item = getRootAdapter().getItem(position); if (!(item instanceof Preference)) return; - + final Preference preference = (Preference) item; preference.performClick(this); } diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index ca1d0d9e371d..fb119b343abd 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -2983,8 +2983,9 @@ public final class ContactsContract { * long streamItemId = ContentUris.parseId(streamItemUri); * </pre> * </dd> - * <dt>Via the {@link StreamItems#CONTENT_URI} URI:</dt> + * <dt>Via {@link StreamItems#CONTENT_URI}:</dt> * <dd> + *<pre> * ContentValues values = new ContentValues(); * values.put(StreamItems.RAW_CONTACT_ID, rawContactId); * values.put(StreamItems.TEXT, "Breakfasted at Tiffanys"); @@ -2992,6 +2993,7 @@ public final class ContactsContract { * values.put(StreamItems.COMMENTS, "3 people reshared this"); * Uri streamItemUri = getContentResolver().insert(StreamItems.CONTENT_URI, values); * long streamItemId = ContentUris.parseId(streamItemUri); + *</pre> * </dd> * </dl> * </dd> @@ -3012,7 +3014,7 @@ public final class ContactsContract { * StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), values); * </pre> * </dd> - * <dt>Via {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI}</dt> + * <dt>Via {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI}:</dt> * <dd> * <pre> * values.clear(); @@ -3021,7 +3023,7 @@ public final class ContactsContract { * values.put(StreamItemPhotos.PHOTO, photoData); * getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values); * </pre> - * Note that this latter form allows the insertion of a stream item and its + * <p>Note that this latter form allows the insertion of a stream item and its * photos in a single transaction, by using {@link ContentProviderOperation} with * back references to populate the stream item ID in the {@link ContentValues}. * </dd> diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index bc5994e371de..bc05078906e6 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1882,6 +1882,11 @@ public final class Settings { /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. + * + * NOTE: Settings are backed up and restored in the order they appear + * in this array. If you have one setting depending on another, + * make sure that they are ordered appropriately. + * * @hide */ public static final String[] SETTINGS_TO_BACKUP = { @@ -4048,6 +4053,12 @@ public final class Settings { public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout"; /** + * This are the settings to be backed up. + * + * NOTE: Settings are backed up and restored in the order they appear + * in this array. If you have one setting depending on another, + * make sure that they are ordered appropriately. + * * @hide */ public static final String[] SETTINGS_TO_BACKUP = { @@ -4056,11 +4067,11 @@ public final class Settings { PARENTAL_CONTROL_ENABLED, PARENTAL_CONTROL_REDIRECT_URL, USB_MASS_STORAGE_ENABLED, - ACCESSIBILITY_ENABLED, ACCESSIBILITY_SCRIPT_INJECTION, BACKUP_AUTO_RESTORE, ENABLED_ACCESSIBILITY_SERVICES, TOUCH_EXPLORATION_ENABLED, + ACCESSIBILITY_ENABLED, TTS_USE_DEFAULTS, TTS_DEFAULT_RATE, TTS_DEFAULT_PITCH, diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index e849b71169fe..237a89250cbe 100755 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -1574,22 +1574,6 @@ public final class Telephony { public static final String SENT_TIME = "sent_time"; } - public static final class ScrapSpace { - /** - * The content:// style URL for this table - */ - public static final Uri CONTENT_URI = Uri.parse("content://mms/scrapSpace"); - - /** - * This is the scrap file we use to store the media attachment when the user - * chooses to capture a photo to be attached . We pass {#link@Uri} to the Camera app, - * which streams the captured image to the uri. Internally we write the media content - * to this file. It's named '.temp.jpg' so Gallery won't pick it up. - */ - public static final String SCRAP_FILE_PATH = - Environment.getExternalStorageDirectory().getPath() + "/mms/scrapSpace/.temp.jpg"; - } - public static final class Intents { private Intents() { // Non-instantiatable. diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index 2f9852d6a816..c3a2308d9df7 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -76,7 +76,7 @@ extends Layout boolean includepad, TextUtils.TruncateAt ellipsize, int ellipsizedWidth) { this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR, - spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth); + spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth, Integer.MAX_VALUE); } /** @@ -93,7 +93,7 @@ extends Layout int width, Alignment align, TextDirectionHeuristic textDir, float spacingmult, float spacingadd, boolean includepad, - TextUtils.TruncateAt ellipsize, int ellipsizedWidth) { + TextUtils.TruncateAt ellipsize, int ellipsizedWidth, int maxLines) { super((ellipsize == null) ? display : (display instanceof Spanned) @@ -135,6 +135,8 @@ extends Layout mEllipsize = true; } + mMaxLines = maxLines; + // Initial state is a single line with 0 characters (0 to 0), // with top at 0 and bottom at whatever is natural, and // undefined ellipsis. @@ -275,7 +277,7 @@ extends Layout } if (reflowed == null) { - reflowed = new StaticLayout(getText()); + reflowed = new StaticLayout(null); } else { reflowed.prepare(); } @@ -283,7 +285,7 @@ extends Layout reflowed.generate(text, where, where + after, getPaint(), getWidth(), getAlignment(), getTextDirectionHeuristic(), getSpacingMultiplier(), getSpacingAdd(), - false, true, mEllipsizedWidth, mEllipsizeAt); + false, true, mEllipsizedWidth, mEllipsizeAt, mMaxLines); int n = reflowed.getLineCount(); // If the new layout has a blank line at the end, but it is not @@ -488,7 +490,9 @@ extends Layout private int mTopPadding, mBottomPadding; - private static StaticLayout sStaticLayout = null; + private int mMaxLines; + + private static StaticLayout sStaticLayout = new StaticLayout(null); private static final Object[] sLock = new Object[0]; diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java index 5fed775dc035..231f9132e6ae 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -709,21 +709,18 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable T ret1 = null; for (int i = 0; i < spanCount; i++) { - if (!kind.isInstance(spans[i])) continue; - int spanStart = starts[i]; - int spanEnd = ends[i]; - if (spanStart > gapstart) { spanStart -= gaplen; } - if (spanEnd > gapstart) { - spanEnd -= gaplen; - } - if (spanStart > queryEnd) { continue; } + + int spanEnd = ends[i]; + if (spanEnd > gapstart) { + spanEnd -= gaplen; + } if (spanEnd < queryStart) { continue; } @@ -735,6 +732,9 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable continue; } + // Expensive test, should be performed after the previous tests + if (!kind.isInstance(spans[i])) continue; + if (count == 0) { // Safe conversion thanks to the isInstance test above ret1 = (T) spans[i]; diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index e8b2045ef828..7c273964fa5d 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -139,7 +139,7 @@ public class StaticLayout extends Layout { generate(source, bufstart, bufend, paint, outerwidth, align, textDir, spacingmult, spacingadd, includepad, includepad, - ellipsizedWidth, ellipsize); + ellipsizedWidth, ellipsize, mMaximumVisibleLineCount); mMeasured = MeasuredText.recycle(mMeasured); mFontMetricsInt = null; @@ -160,7 +160,7 @@ public class StaticLayout extends Layout { Alignment align, TextDirectionHeuristic textDir, float spacingmult, float spacingadd, boolean includepad, boolean trackpad, - float ellipsizedWidth, TextUtils.TruncateAt ellipsize) { + float ellipsizedWidth, TextUtils.TruncateAt ellipsize, int maxLines) { mLineCount = 0; int v = 0; @@ -477,13 +477,13 @@ public class StaticLayout extends Layout { width = restWidth; } } - if (mLineCount >= mMaximumVisibleLineCount) { + if (mLineCount >= maxLines) { break; } } } - if (paraEnd != here && mLineCount < mMaximumVisibleLineCount) { + if (paraEnd != here && mLineCount < maxLines) { if ((fitTop | fitBottom | fitDescent | fitAscent) == 0) { paint.getFontMetricsInt(fm); @@ -514,7 +514,7 @@ public class StaticLayout extends Layout { } if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && - mLineCount < mMaximumVisibleLineCount) { + mLineCount < maxLines) { // Log.e("text", "output last " + bufEnd); paint.getFontMetricsInt(fm); @@ -763,7 +763,8 @@ public class StaticLayout extends Layout { return; } - float ellipsisWidth = paint.measureText(HORIZONTAL_ELLIPSIS); + float ellipsisWidth = paint.measureText( + (where == TextUtils.TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL); int ellipsisStart = 0; int ellipsisCount = 0; int len = lineEnd - lineStart; @@ -791,7 +792,8 @@ public class StaticLayout extends Layout { Log.w(TAG, "Start Ellipsis only supported with one line"); } } - } else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE) { + } else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE || + where == TextUtils.TruncateAt.END_SMALL) { float sum = 0; int i; @@ -1001,7 +1003,9 @@ public class StaticLayout extends Layout { private static final char CHAR_HYPHEN = '-'; private static final double EXTRA_ROUNDING = 0.5; - private static final String HORIZONTAL_ELLIPSIS = "\u2026"; // this is "..." + + private static final String ELLIPSIS_NORMAL = "\u2026"; // this is "..." + private static final String ELLIPSIS_TWO_DOTS = "\u2025"; // this is ".." private static final int CHAR_FIRST_HIGH_SURROGATE = 0xD800; private static final int CHAR_LAST_LOW_SURROGATE = 0xDFFF; diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index a52d48e630d1..68fea1907b87 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -30,6 +30,8 @@ import android.util.Log; import com.android.internal.util.ArrayUtils; +import java.lang.reflect.Array; + /** * Represents a line of styled text, for measuring in visual order and * for rendering. @@ -679,6 +681,12 @@ class TextLine { wp.getFontMetricsInt(fmi); + updateMetrics(fmi, previousTop, previousAscent, previousDescent, previousBottom, + previousLeading); + } + + static void updateMetrics(FontMetricsInt fmi, int previousTop, int previousAscent, + int previousDescent, int previousBottom, int previousLeading) { fmi.top = Math.min(fmi.top, previousTop); fmi.ascent = Math.min(fmi.ascent, previousAscent); fmi.descent = Math.max(fmi.descent, previousDescent); @@ -809,7 +817,28 @@ class TextLine { int textLimit = mStart + limit; if (needWidth || (c != null && runIsRtl)) { + int previousTop = 0; + int previousAscent = 0; + int previousDescent = 0; + int previousBottom = 0; + int previousLeading = 0; + + boolean needUpdateMetrics = (fmi != null); + + if (needUpdateMetrics) { + previousTop = fmi.top; + previousAscent = fmi.ascent; + previousDescent = fmi.descent; + previousBottom = fmi.bottom; + previousLeading = fmi.leading; + } + ret = replacement.getSize(wp, mText, textStart, textLimit, fmi); + + if (needUpdateMetrics) { + updateMetrics(fmi, previousTop, previousAscent, previousDescent, previousBottom, + previousLeading); + } } if (c != null) { @@ -823,6 +852,73 @@ class TextLine { return runIsRtl ? -ret : ret; } + private static class SpanSet<E> { + final int numberOfSpans; + final E[] spans; + final int[] spanStarts; + final int[] spanEnds; + final int[] spanFlags; + + @SuppressWarnings("unchecked") + SpanSet(Spanned spanned, int start, int limit, Class<? extends E> type) { + final E[] allSpans = spanned.getSpans(start, limit, type); + final int length = allSpans.length; + // These arrays may end up being too large because of empty spans + spans = (E[]) Array.newInstance(type, length); + spanStarts = new int[length]; + spanEnds = new int[length]; + spanFlags = new int[length]; + + int count = 0; + for (int i = 0; i < length; i++) { + final E span = allSpans[i]; + + final int spanStart = spanned.getSpanStart(span); + final int spanEnd = spanned.getSpanEnd(span); + if (spanStart == spanEnd) continue; + + final int spanFlag = spanned.getSpanFlags(span); + final int priority = spanFlag & Spanned.SPAN_PRIORITY; + if (priority != 0 && count != 0) { + int j; + + for (j = 0; j < count; j++) { + final int otherPriority = spanFlags[j] & Spanned.SPAN_PRIORITY; + if (priority > otherPriority) break; + } + + System.arraycopy(spans, j, spans, j + 1, count - j); + System.arraycopy(spanStarts, j, spanStarts, j + 1, count - j); + System.arraycopy(spanEnds, j, spanEnds, j + 1, count - j); + System.arraycopy(spanFlags, j, spanFlags, j + 1, count - j); + + spans[j] = span; + spanStarts[j] = spanStart; + spanEnds[j] = spanEnd; + spanFlags[j] = spanFlag; + } else { + spans[i] = span; + spanStarts[i] = spanStart; + spanEnds[i] = spanEnd; + spanFlags[i] = spanFlag; + } + + count++; + } + numberOfSpans = count; + } + + int getNextTransition(int start, int limit) { + for (int i = 0; i < numberOfSpans; i++) { + final int spanStart = spanStarts[i]; + final int spanEnd = spanEnds[i]; + if (spanStart > start && spanStart < limit) limit = spanStart; + if (spanEnd > start && spanEnd < limit) limit = spanEnd; + } + return limit; + } + } + /** * Utility function for handling a unidirectional run. The run must not * contain tabs or emoji but can contain styles. @@ -856,66 +952,70 @@ class TextLine { return 0f; } + if (mSpanned == null) { + TextPaint wp = mWorkPaint; + wp.set(mPaint); + final int mlimit = measureLimit; + return handleText(wp, start, mlimit, start, limit, runIsRtl, c, x, top, + y, bottom, fmi, needWidth || mlimit < measureLimit); + } + + final SpanSet<MetricAffectingSpan> metricAffectingSpans = new SpanSet<MetricAffectingSpan>( + mSpanned, mStart + start, mStart + limit, MetricAffectingSpan.class); + final SpanSet<CharacterStyle> characterStyleSpans = new SpanSet<CharacterStyle>( + mSpanned, mStart + start, mStart + limit, CharacterStyle.class); + // Shaping needs to take into account context up to metric boundaries, // but rendering needs to take into account character style boundaries. // So we iterate through metric runs to get metric bounds, // then within each metric run iterate through character style runs // for the run bounds. - float ox = x; + final float originalX = x; for (int i = start, inext; i < measureLimit; i = inext) { TextPaint wp = mWorkPaint; wp.set(mPaint); - int mlimit; - if (mSpanned == null) { - inext = limit; - mlimit = measureLimit; - } else { - inext = mSpanned.nextSpanTransition(mStart + i, mStart + limit, - MetricAffectingSpan.class) - mStart; - - mlimit = inext < measureLimit ? inext : measureLimit; - MetricAffectingSpan[] spans = mSpanned.getSpans(mStart + i, - mStart + mlimit, MetricAffectingSpan.class); - spans = TextUtils.removeEmptySpans(spans, mSpanned, MetricAffectingSpan.class); - - if (spans.length > 0) { - ReplacementSpan replacement = null; - for (int j = 0; j < spans.length; j++) { - MetricAffectingSpan span = spans[j]; - if (span instanceof ReplacementSpan) { - replacement = (ReplacementSpan)span; - } else { - // We might have a replacement that uses the draw - // state, otherwise measure state would suffice. - span.updateDrawState(wp); - } - } - - if (replacement != null) { - x += handleReplacement(replacement, wp, i, - mlimit, runIsRtl, c, x, top, y, bottom, fmi, - needWidth || mlimit < measureLimit); - continue; - } + inext = metricAffectingSpans.getNextTransition(mStart + i, mStart + limit) - mStart; + int mlimit = Math.min(inext, measureLimit); + + ReplacementSpan replacement = null; + + for (int j = 0; j < metricAffectingSpans.numberOfSpans; j++) { + // Both intervals [spanStarts..spanEnds] and [mStart + i..mStart + mlimit] are NOT + // empty by construction. This special case in getSpans() explains the >= & <= tests + if ((metricAffectingSpans.spanStarts[j] >= mStart + mlimit) || + (metricAffectingSpans.spanEnds[j] <= mStart + i)) continue; + MetricAffectingSpan span = metricAffectingSpans.spans[j]; + if (span instanceof ReplacementSpan) { + replacement = (ReplacementSpan)span; + } else { + // We might have a replacement that uses the draw + // state, otherwise measure state would suffice. + span.updateDrawState(wp); } } - if (mSpanned == null || c == null) { + if (replacement != null) { + x += handleReplacement(replacement, wp, i, mlimit, runIsRtl, c, x, top, y, + bottom, fmi, needWidth || mlimit < measureLimit); + continue; + } + + if (c == null) { x += handleText(wp, i, mlimit, i, inext, runIsRtl, c, x, top, y, bottom, fmi, needWidth || mlimit < measureLimit); } else { for (int j = i, jnext; j < mlimit; j = jnext) { - jnext = mSpanned.nextSpanTransition(mStart + j, - mStart + mlimit, CharacterStyle.class) - mStart; - - CharacterStyle[] spans = mSpanned.getSpans(mStart + j, - mStart + jnext, CharacterStyle.class); - spans = TextUtils.removeEmptySpans(spans, mSpanned, CharacterStyle.class); + jnext = characterStyleSpans.getNextTransition(mStart + j, mStart + mlimit) - + mStart; wp.set(mPaint); - for (int k = 0; k < spans.length; k++) { - CharacterStyle span = spans[k]; + for (int k = 0; k < characterStyleSpans.numberOfSpans; k++) { + // Intentionally using >= and <= as explained above + if ((characterStyleSpans.spanStarts[k] >= mStart + jnext) || + (characterStyleSpans.spanEnds[k] <= mStart + j)) continue; + + CharacterStyle span = characterStyleSpans.spans[k]; span.updateDrawState(wp); } @@ -925,7 +1025,7 @@ class TextLine { } } - return x - ox; + return x - originalX; } /** @@ -970,8 +1070,7 @@ class TextLine { } pos += mStart; - MetricAffectingSpan[] spans = mSpanned.getSpans(pos, pos + 1, - MetricAffectingSpan.class); + MetricAffectingSpan[] spans = mSpanned.getSpans(pos, pos + 1, MetricAffectingSpan.class); if (spans.length == 0) { return mPaint.ascent(); } diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 894afbdc20ef..95a3cdc6ad8d 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -53,9 +53,8 @@ import java.util.Iterator; import java.util.regex.Pattern; public class TextUtils { - private TextUtils() { /* cannot be instantiated */ } - private static String[] EMPTY_STRING_ARRAY = new String[]{}; + private TextUtils() { /* cannot be instantiated */ } public static void getChars(CharSequence s, int start, int end, char[] dest, int destoff) { @@ -1000,6 +999,10 @@ public class TextUtils { MIDDLE, END, MARQUEE, + /** + * @hide + */ + END_SMALL } public interface EllipsizeCallback { @@ -1010,8 +1013,6 @@ public class TextUtils { public void ellipsized(int start, int end); } - private static String sEllipsis = null; - /** * Returns the original text if it fits in the specified width * given the properties of the specified Paint, @@ -1042,7 +1043,8 @@ public class TextUtils { boolean preserveLength, EllipsizeCallback callback) { return ellipsize(text, paint, avail, where, preserveLength, callback, - TextDirectionHeuristics.FIRSTSTRONG_LTR); + TextDirectionHeuristics.FIRSTSTRONG_LTR, + (where == TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL); } /** @@ -1063,11 +1065,7 @@ public class TextUtils { float avail, TruncateAt where, boolean preserveLength, EllipsizeCallback callback, - TextDirectionHeuristic textDir) { - if (sEllipsis == null) { - Resources r = Resources.getSystem(); - sEllipsis = r.getString(R.string.ellipsis); - } + TextDirectionHeuristic textDir, String ellipsis) { int len = text.length(); @@ -1085,7 +1083,7 @@ public class TextUtils { // XXX assumes ellipsis string does not require shaping and // is unaffected by style - float ellipsiswid = paint.measureText(sEllipsis); + float ellipsiswid = paint.measureText(ellipsis); avail -= ellipsiswid; int left = 0; @@ -1094,7 +1092,7 @@ public class TextUtils { // it all goes } else if (where == TruncateAt.START) { right = len - mt.breakText(0, len, false, avail); - } else if (where == TruncateAt.END) { + } else if (where == TruncateAt.END || where == TruncateAt.END_SMALL) { left = mt.breakText(0, len, true, avail); } else { right = len - mt.breakText(0, len, false, avail / 2); @@ -1112,10 +1110,10 @@ public class TextUtils { int remaining = len - (right - left); if (preserveLength) { if (remaining > 0) { // else eliminate the ellipsis too - buf[left++] = '\u2026'; + buf[left++] = ellipsis.charAt(0); } for (int i = left; i < right; i++) { - buf[i] = '\uFEFF'; + buf[i] = ZWNBS_CHAR; } String s = new String(buf, 0, len); if (sp == null) { @@ -1131,16 +1129,16 @@ public class TextUtils { } if (sp == null) { - StringBuilder sb = new StringBuilder(remaining + sEllipsis.length()); + StringBuilder sb = new StringBuilder(remaining + ellipsis.length()); sb.append(buf, 0, left); - sb.append(sEllipsis); + sb.append(ellipsis); sb.append(buf, right, len - right); return sb.toString(); } SpannableStringBuilder ssb = new SpannableStringBuilder(); ssb.append(text, 0, left); - ssb.append(sEllipsis); + ssb.append(ellipsis); ssb.append(text, right, len); return ssb; } finally { @@ -1664,4 +1662,13 @@ public class TextUtils { private static Object sLock = new Object(); private static char[] sTemp = null; + + private static String[] EMPTY_STRING_ARRAY = new String[]{}; + + private static final char ZWNBS_CHAR = '\uFEFF'; + + private static final String ELLIPSIS_NORMAL = Resources.getSystem().getString( + R.string.ellipsis); + private static final String ELLIPSIS_TWO_DOTS = Resources.getSystem().getString( + R.string.ellipsis_two_dots); } diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java index 5926db3713db..b4445ca1e0ed 100644 --- a/core/java/android/text/format/Time.java +++ b/core/java/android/text/format/Time.java @@ -22,8 +22,8 @@ import java.util.Locale; import java.util.TimeZone; /** - * The Time class is a faster replacement for the java.util.Calendar and - * java.util.GregorianCalendar classes. An instance of the Time class represents + * An alternative to the {@link java.util.Calendar} and + * {@link java.util.GregorianCalendar} classes. An instance of the Time class represents * a moment in time, specified with second precision. It is modelled after * struct tm, and in fact, uses struct tm to implement most of the * functionality. @@ -79,7 +79,7 @@ public class Time { public int month; /** - * Year. TBD. Is this years since 1900 like in struct tm? + * Year. For example, 1970. */ public int year; diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java index 3f9b94563a0b..106a80190b36 100644 --- a/core/java/android/text/method/Touch.java +++ b/core/java/android/text/method/Touch.java @@ -35,44 +35,39 @@ public class Touch { * Y position. */ public static void scrollTo(TextView widget, Layout layout, int x, int y) { - int padding = widget.getTotalPaddingTop() + - widget.getTotalPaddingBottom(); - int top = layout.getLineForVertical(y); - int bottom = layout.getLineForVertical(y + widget.getHeight() - - padding); + final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(); + final int top = layout.getLineForVertical(y); + final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding); int left = Integer.MAX_VALUE; int right = 0; - Alignment a = null; - boolean ltr = true; + Alignment a = layout.getParagraphAlignment(top); + boolean ltr = layout.getParagraphDirection(top) > 0; for (int i = top; i <= bottom; i++) { left = (int) Math.min(left, layout.getLineLeft(i)); right = (int) Math.max(right, layout.getLineRight(i)); - - if (a == null) { - a = layout.getParagraphAlignment(i); - ltr = layout.getParagraphDirection(i) > 0; - } } - padding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight(); - int width = widget.getWidth(); - int diff = 0; + final int hoizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight(); + final int availableWidth = widget.getWidth() - hoizontalPadding; + final int actualWidth = right - left; - // align_opposite does NOT mean align_right, we need the paragraph - // direction to resolve it to left or right - if (right - left < width - padding) { + if (actualWidth < availableWidth) { if (a == Alignment.ALIGN_CENTER) { - diff = (width - padding - (right - left)) / 2; - } else if (ltr == (a == Alignment.ALIGN_OPPOSITE)) { - diff = width - padding - (right - left); + x = left - ((availableWidth - actualWidth) / 2); + } else if ((ltr && (a == Alignment.ALIGN_OPPOSITE)) || (a == Alignment.ALIGN_RIGHT)) { + // align_opposite does NOT mean align_right, we need the paragraph + // direction to resolve it to left or right + x = left - (availableWidth - actualWidth); + } else { + x = left; } + } else { + x = Math.min(x, right - availableWidth); + x = Math.max(x, left); } - x = Math.min(x, right - (width - padding) - diff); - x = Math.max(x, left - diff); - widget.scrollTo(x, y); } diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java index 0433ec4d604f..af524eedfe68 100644 --- a/core/java/android/text/method/WordIterator.java +++ b/core/java/android/text/method/WordIterator.java @@ -73,10 +73,6 @@ public class WordIterator implements Selection.PositionIterator { } }; - public void forceUpdate() { - mCurrentDirty = true; - } - public void setCharSequence(CharSequence incoming) { // When incoming is different object, move listeners to new sequence // and mark as dirty so we reload contents. diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java index caaae99630a1..0d8a1034ed8f 100644 --- a/core/java/android/text/style/SpellCheckSpan.java +++ b/core/java/android/text/style/SpellCheckSpan.java @@ -39,8 +39,8 @@ public class SpellCheckSpan implements ParcelableSpan { mSpellCheckInProgress = (src.readInt() != 0); } - public void setSpellCheckInProgress() { - mSpellCheckInProgress = true; + public void setSpellCheckInProgress(boolean inProgress) { + mSpellCheckInProgress = inProgress; } public boolean isSpellCheckInProgress() { diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java index 5601dc526c2f..ed976ab1d6b6 100644 --- a/core/java/android/view/ActionProvider.java +++ b/core/java/android/view/ActionProvider.java @@ -58,6 +58,7 @@ import android.content.Context; * @see MenuItem#getActionProvider() */ public abstract class ActionProvider { + private SubUiVisibilityListener mSubUiVisibilityListener; /** * Creates a new instance. @@ -138,4 +139,31 @@ public abstract class ActionProvider { */ public void onPrepareSubMenu(SubMenu subMenu) { } + + /** + * Notify the system that the visibility of an action view's sub-UI such as + * an anchored popup has changed. This will affect how other system + * visibility notifications occur. + * + * @hide Pending future API approval + */ + public void subUiVisibilityChanged(boolean isVisible) { + if (mSubUiVisibilityListener != null) { + mSubUiVisibilityListener.onSubUiVisibilityChanged(isVisible); + } + } + + /** + * @hide Internal use only + */ + public void setSubUiVisibilityListener(SubUiVisibilityListener listener) { + mSubUiVisibilityListener = listener; + } + + /** + * @hide Internal use only + */ + public interface SubUiVisibilityListener { + public void onSubUiVisibilityChanged(boolean isVisible); + } } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 335c66b036dc..45f9da21c435 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -116,6 +116,7 @@ interface IWindowManager boolean isKeyguardLocked(); boolean isKeyguardSecure(); boolean inKeyguardRestrictedInputMode(); + void dismissKeyguard(); void closeSystemDialogs(String reason); @@ -163,15 +164,13 @@ interface IWindowManager // These can only be called with the SET_ORIENTATION permission. /** - * Change the current screen rotation, constants as per - * {@link android.view.Surface}. - * @param rotation the intended rotation. + * Update the current screen rotation based on the current state of + * the world. * @param alwaysSendConfiguration Flag to force a new configuration to * be evaluated. This can be used when there are other parameters in * configuration that are changing. - * @param animFlags Animation flags as per {@link android.view.Surface}. */ - void setRotation(int rotation, boolean alwaysSendConfiguration, int animFlags); + void updateRotation(boolean alwaysSendConfiguration); /** * Retrieve the current screen orientation, constants as per diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 3880bc45b4f3..64d3d3101cdb 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -207,9 +207,6 @@ public class Surface implements Parcelable { /** Enable dithering when compositing this surface @hide */ public static final int SURFACE_DITHER = 0x04; - - /** Disable the orientation animation @hide */ - public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001; // The mSurfaceControl will only be present for Surfaces used by the window // server or system processes. When this class is parceled we defer to the @@ -393,7 +390,7 @@ public class Surface implements Parcelable { * set the orientation of the given display. * @param display * @param orientation - * @param flags + * @param flags Currently unused, set to 0. * @hide */ public static native void setOrientation(int display, int orientation, int flags); diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index c735d6bddba6..d57132aef84d 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -93,6 +93,11 @@ import android.util.Log; * been invoked.) It is therefore highly recommended you use a listener to * be notified when the SurfaceTexture becomes available.</p> * + * <p>It is important to note that only one producer can use the TextureView. + * For instance, if you use a TextureView to display the camera preview, you + * cannot use {@link #lockCanvas()} to draw onto the TextureView at the same + * time.</p> + * * @see SurfaceView * @see SurfaceTexture */ @@ -245,6 +250,11 @@ public class TextureView extends View { return LAYER_TYPE_HARDWARE; } + @Override + boolean hasStaticLayer() { + return true; + } + /** * Calling this method has no effect. */ @@ -523,6 +533,10 @@ public class TextureView extends View { * rectangle is specified, in which case, non-dirty pixels will be * preserved.</p> * + * <p>This method can only be used if the underlying surface is not already + * owned by another producer. For instance, if the TextureView is being used + * to render the camera's preview you cannot invoke this method.</p> + * * @return A Canvas used to draw into the surface. * * @see #lockCanvas(android.graphics.Rect) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index ca06b9cf118a..d193d6e41504 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -81,7 +81,6 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Locale; -import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArrayList; /** @@ -1497,12 +1496,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal /** * Map used to store views' tags. */ - private static WeakHashMap<View, SparseArray<Object>> sTags; - - /** - * Lock used to access sTags. - */ - private static final Object sTagsLock = new Object(); + private SparseArray<Object> mKeyedTags; /** * The next available accessiiblity id. @@ -2915,6 +2909,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal initializeScrollbars(a); } break; + //noinspection deprecation case R.styleable.View_fadingEdge: if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) { // Ignore the attribute starting with ICS @@ -3900,6 +3895,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * Note: Called from the default {@link AccessibilityDelegate}. */ boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { + // Do not populate text to scroll events. They describe position change + // and usually come from container with a lot of text which is not very + // informative for accessibility purposes. Also they are fired frequently. + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { + return true; + } onPopulateAccessibilityEvent(event); return false; } @@ -10000,6 +10001,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } /** + * Indicates whether this view has a static layer. A view with layer type + * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are + * dynamic. + */ + boolean hasStaticLayer() { + return mLayerType == LAYER_TYPE_NONE; + } + + /** * Indicates what type of layer is currently associated with this view. By default * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} @@ -12236,14 +12246,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * @see #getTag() */ public Object getTag(int key) { - SparseArray<Object> tags = null; - synchronized (sTagsLock) { - if (sTags != null) { - tags = sTags.get(this); - } - } - - if (tags != null) return tags.get(key); + if (mKeyedTags != null) return mKeyedTags.get(key); return null; } @@ -12276,7 +12279,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal + "resource id."); } - setTagInternal(this, key, tag); + setKeyedTag(key, tag); } /** @@ -12291,27 +12294,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal + "resource id."); } - setTagInternal(this, key, tag); + setKeyedTag(key, tag); } - private static void setTagInternal(View view, int key, Object tag) { - SparseArray<Object> tags = null; - synchronized (sTagsLock) { - if (sTags == null) { - sTags = new WeakHashMap<View, SparseArray<Object>>(); - } else { - tags = sTags.get(view); - } - } - - if (tags == null) { - tags = new SparseArray<Object>(2); - synchronized (sTagsLock) { - sTags.put(view, tags); - } + private void setKeyedTag(int key, Object tag) { + if (mKeyedTags == null) { + mKeyedTags = new SparseArray<Object>(); } - tags.put(key, tag); + mKeyedTags.put(key, tag); } /** @@ -12969,15 +12960,13 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * Request that the visibility of the status bar be changed. * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. - * - * This value will be re-applied immediately, even if the flags have not changed, so a view may - * easily reassert a particular SystemUiVisibility condition even if the system UI itself has - * since countermanded the original request. */ public void setSystemUiVisibility(int visibility) { - mSystemUiVisibility = visibility; - if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { - mParent.recomputeViewAttributes(this); + if (visibility != mSystemUiVisibility) { + mSystemUiVisibility = visibility; + if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { + mParent.recomputeViewAttributes(this); + } } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index b678c7dab894..fb0d80a688e4 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -34,7 +34,6 @@ import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; -import android.view.View.AccessibilityDelegate; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Animation; @@ -615,9 +614,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Called when a child has requested sending an {@link AccessibilityEvent} and * gives an opportunity to its parent to augment the event. * <p> - * If an {@link AccessibilityDelegate} has been specified via calling - * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its - * {@link AccessibilityDelegate#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)} + * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling + * {@link android.view.View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its + * {@link android.view.View.AccessibilityDelegate#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)} * is responsible for handling this call. * </p> * @@ -2176,13 +2175,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { - // We first get a chance to populate the event. - super.dispatchPopulateAccessibilityEventInternal(event); + boolean handled = super.dispatchPopulateAccessibilityEventInternal(event); + if (handled) { + return handled; + } // Let our children have a shot in populating the event. for (int i = 0, count = getChildCount(); i < count; i++) { View child = getChildAt(i); if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { - boolean handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event); + handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event); if (handled) { return handled; } @@ -2559,7 +2560,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final View[] children = mChildren; for (int i = 0; i < count; i++) { final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { + if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) && + child.hasStaticLayer()) { child.mRecreateDisplayList = (child.mPrivateFlags & INVALIDATED) == INVALIDATED; child.mPrivateFlags &= ~INVALIDATED; child.getDisplayList(); @@ -2822,6 +2824,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (hasDisplayList) { displayList = child.getDisplayList(); + if (!displayList.isValid()) { + // Uncommon, but possible. If a view is removed from the hierarchy during the call + // to getDisplayList(), the display list will be marked invalid and we should not + // try to use it again. + displayList = null; + hasDisplayList = false; + } } if (hasNoCache) { diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 75c75927a769..d0841dd2b3e7 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; +import android.os.SystemProperties; import android.util.Slog; import android.view.accessibility.AccessibilityEvent; @@ -472,11 +473,14 @@ public abstract class Window { } private class LocalWindowManager extends WindowManagerImpl.CompatModeWrapper { + private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw"; + private final boolean mHardwareAccelerated; LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) { super(wm, getCompatInfo(mContext)); - mHardwareAccelerated = hardwareAccelerated; + mHardwareAccelerated = hardwareAccelerated || + SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false); } public boolean isHardwareAccelerated() { diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index c07faf63d222..4f67675c1aed 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -375,12 +375,6 @@ public interface WindowManagerPolicy { /** Screen turned off because of proximity sensor */ public final int OFF_BECAUSE_OF_PROX_SENSOR = 4; - /** - * Magic constant to {@link IWindowManager#setRotation} to not actually - * modify the rotation. - */ - public final int USE_LAST_ROTATION = -1000; - /** When not otherwise specified by the activity's screenOrientation, rotation should be * determined by the system (that is, using sensors). */ public final int USER_ROTATION_FREE = 0; @@ -856,22 +850,42 @@ public interface WindowManagerPolicy { public boolean inKeyguardRestrictedKeyInputMode(); /** - * Given an orientation constant - * ({@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE - * ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE} or - * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_PORTRAIT - * ActivityInfo.SCREEN_ORIENTATION_PORTRAIT}), return a surface - * rotation. + * Ask the policy to dismiss the keyguard, if it is currently shown. */ - public int rotationForOrientationLw(int orientation, int lastRotation, - boolean displayEnabled); - + public void dismissKeyguardLw(); + + /** + * Given an orientation constant, returns the appropriate surface rotation, + * taking into account sensors, docking mode, rotation lock, and other factors. + * + * @param orientation An orientation constant, such as + * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}. + * @param lastRotation The most recently used rotation. + * @return The surface rotation to use. + */ + public int rotationForOrientationLw(int orientation, int lastRotation); + /** - * Return the currently locked screen rotation, if any. Return - * Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180, or - * Surface.ROTATION_270 if locked; return -1 if not locked. + * Given an orientation constant and a rotation, returns true if the rotation + * has compatible metrics to the requested orientation. For example, if + * the application requested landscape and got seascape, then the rotation + * has compatible metrics; if the application requested portrait and got landscape, + * then the rotation has incompatible metrics; if the application did not specify + * a preference, then anything goes. + * + * @param orientation An orientation constant, such as + * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}. + * @param rotation The rotation to check. + * @return True if the rotation is compatible with the requested orientation. + */ + public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation); + + /** + * Called by the window manager when the rotation changes. + * + * @param rotation The new rotation. */ - public int getLockedRotationLw(); + public void setRotationLw(int rotation); /** * Called when the system is mostly done booting to determine whether diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java index 76b47ca5a5e5..c3c74a7c59c5 100755 --- a/core/java/android/view/WindowOrientationListener.java +++ b/core/java/android/view/WindowOrientationListener.java @@ -26,7 +26,7 @@ import android.util.Slog; /** * A special helper class used by the WindowManager - * for receiving notifications from the SensorManager when + * for receiving notifications from the SensorManager when * the orientation of the device has changed. * * NOTE: If changing anything here, please run the API demo @@ -54,6 +54,7 @@ public abstract class WindowOrientationListener { private Sensor mSensor; private SensorEventListenerImpl mSensorEventListener; boolean mLogEnabled; + int mCurrentRotation = -1; /** * Creates a new WindowOrientationListener. @@ -117,15 +118,27 @@ public abstract class WindowOrientationListener { } /** - * Gets the current orientation. - * @param lastRotation - * @return + * Sets the current rotation. + * + * @param rotation The current rotation. + */ + public void setCurrentRotation(int rotation) { + mCurrentRotation = rotation; + } + + /** + * Gets the proposed rotation. + * + * This method only returns a rotation if the orientation listener is certain + * of its proposal. If the rotation is indeterminate, returns -1. + * + * @return The proposed rotation, or -1 if unknown. */ - public int getCurrentRotation(int lastRotation) { + public int getProposedRotation() { if (mEnabled) { - return mSensorEventListener.getCurrentRotation(lastRotation); + return mSensorEventListener.getProposedRotation(); } - return lastRotation; + return -1; } /** @@ -138,10 +151,14 @@ public abstract class WindowOrientationListener { /** * Called when the rotation view of the device has changed. * + * This method is called whenever the orientation becomes certain of an orientation. + * It is called each time the orientation determination transitions from being + * uncertain to being certain again, even if it is the same orientation as before. + * * @param rotation The new orientation of the device, one of the Surface.ROTATION_* constants. * @see Surface */ - public abstract void onOrientationChanged(int rotation); + public abstract void onProposedRotationChanged(int rotation); /** * Enables or disables the window orientation listener logging for use with @@ -183,23 +200,8 @@ public abstract class WindowOrientationListener { * to the corresponding orientation. These thresholds have some hysteresis built-in * to avoid oscillations between adjacent orientations. * - * - Use the magnitude to judge the confidence of the orientation. - * Under ideal conditions, the magnitude should equal to that of gravity. When it - * differs significantly, we know the device is under external acceleration and - * we can't trust the data. - * - * - Use the tilt angle to judge the confidence of the orientation. - * When the tilt angle is high in absolute value then the device is nearly flat - * so small physical movements produce large changes in orientation angle. - * This can be the case when the device is being picked up from a table. - * - * - Use the orientation angle to judge the confidence of the orientation. - * The close the orientation angle is to the canonical orientation angle, the better. - * - * - Based on the aggregate confidence, we determine how long we want to wait for - * the new orientation to settle. This is accomplished by integrating the confidence - * for each orientation over time. When a threshold integration sum is reached - * then we actually change orientations. + * - Wait for the device to settle for a little bit. Once that happens, issue the + * new orientation proposal. * * Details are explained inline. */ @@ -212,22 +214,8 @@ public abstract class WindowOrientationListener { private static final int ACCELEROMETER_DATA_Y = 1; private static final int ACCELEROMETER_DATA_Z = 2; - // Rotation constants. - // These are the same as Surface rotation constants with the addition of a 5th - // unknown state when we are not confident about the proporsed orientation. - // One important property of these constants is that they are equal to the - // orientation angle itself divided by 90. We use this fact to map - // back and forth between orientation angles and rotation values. - private static final int ROTATION_UNKNOWN = -1; - //private static final int ROTATION_0 = Surface.ROTATION_0; // 0 - //private static final int ROTATION_90 = Surface.ROTATION_90; // 1 - //private static final int ROTATION_180 = Surface.ROTATION_180; // 2 - //private static final int ROTATION_270 = Surface.ROTATION_270; // 3 - private final WindowOrientationListener mOrientationListener; - private int mRotation = ROTATION_UNKNOWN; - /* State for first order low-pass filtering of accelerometer data. * See http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization for * signal processing background. @@ -236,6 +224,24 @@ public abstract class WindowOrientationListener { private long mLastTimestamp = Long.MAX_VALUE; // in nanoseconds private float mLastFilteredX, mLastFilteredY, mLastFilteredZ; + // The current proposal. We wait for the proposal to be stable for a + // certain amount of time before accepting it. + // + // The basic idea is to ignore intermediate poses of the device while the + // user is picking up, putting down or turning the device. + private int mProposalRotation; + private long mProposalAgeMS; + + // A historical trace of tilt and orientation angles. Used to determine whether + // the device posture has settled down. + private static final int HISTORY_SIZE = 20; + private int mHistoryIndex; // index of most recent sample + private int mHistoryLength; // length of historical trace + private final long[] mHistoryTimestampMS = new long[HISTORY_SIZE]; + private final float[] mHistoryMagnitudes = new float[HISTORY_SIZE]; + private final int[] mHistoryTiltAngles = new int[HISTORY_SIZE]; + private final int[] mHistoryOrientationAngles = new int[HISTORY_SIZE]; + // The maximum sample inter-arrival time in milliseconds. // If the acceleration samples are further apart than this amount in time, we reset the // state of the low-pass filter and orientation properties. This helps to handle @@ -243,24 +249,26 @@ public abstract class WindowOrientationListener { // a significant gap in samples. private static final float MAX_FILTER_DELTA_TIME_MS = 1000; - // The acceleration filter cutoff frequency. - // This is the frequency at which signals are attenuated by 3dB (half the passband power). + // The acceleration filter time constant. + // + // This time constant is used to tune the acceleration filter such that + // impulses and vibrational noise (think car dock) is suppressed before we + // try to calculate the tilt and orientation angles. + // + // The filter time constant is related to the filter cutoff frequency, which is the + // frequency at which signals are attenuated by 3dB (half the passband power). // Each successive octave beyond this frequency is attenuated by an additional 6dB. // - // We choose the cutoff frequency such that impulses and vibrational noise - // (think car dock) is suppressed. However, this filtering does not eliminate - // all possible sources of orientation ambiguity so we also rely on a dynamic - // settle time for establishing a new orientation. Filtering adds latency - // inversely proportional to the cutoff frequency so we don't want to make - // it too small or we can lose hundreds of milliseconds of responsiveness. - private static final float FILTER_CUTOFF_FREQUENCY_HZ = 1f; - private static final float FILTER_TIME_CONSTANT_MS = (float)(500.0f - / (Math.PI * FILTER_CUTOFF_FREQUENCY_HZ)); // t = 1 / (2pi * Fc) * 1000ms - - // The filter gain. - // We choose a value slightly less than unity to avoid numerical instabilities due - // to floating-point error accumulation. - private static final float FILTER_GAIN = 0.999f; + // Given a time constant t in seconds, the filter cutoff frequency Fc in Hertz + // is given by Fc = 1 / (2pi * t). + // + // The higher the time constant, the lower the cutoff frequency, so more noise + // will be suppressed. + // + // Filtering adds latency proportional the time constant (inversely proportional + // to the cutoff frequency) so we don't want to make the time constant too + // large or we can lose responsiveness. + private static final float FILTER_TIME_CONSTANT_MS = 100.0f; /* State for orientation detection. */ @@ -298,10 +306,10 @@ public abstract class WindowOrientationListener { // The ideal tilt angle is 0 (when the device is vertical) so the limits establish // how close to vertical the device must be in order to change orientation. private static final int[][] TILT_TOLERANCE = new int[][] { - /* ROTATION_0 */ { -20, 75 }, - /* ROTATION_90 */ { -20, 70 }, - /* ROTATION_180 */ { -20, 65 }, - /* ROTATION_270 */ { -20, 70 } + /* ROTATION_0 */ { -20, 70 }, + /* ROTATION_90 */ { -20, 60 }, + /* ROTATION_180 */ { -20, 50 }, + /* ROTATION_270 */ { -20, 60 } }; // The gap angle in degrees between adjacent orientation angles for hysteresis. @@ -309,41 +317,31 @@ public abstract class WindowOrientationListener { // adjacent orientation. No orientation proposal is made when the orientation // angle is within the gap between the current orientation and the adjacent // orientation. - private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 30; - - // The confidence scale factors for angle, tilt and magnitude. - // When the distance between the actual value and the ideal value is the - // specified delta, orientation transitions will take twice as long as they would - // in the ideal case. Increasing or decreasing the delta has an exponential effect - // on each factor's influence over the transition time. + private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 45; - // Transition takes 2x longer when angle is 30 degrees from ideal orientation angle. - private static final float ORIENTATION_ANGLE_CONFIDENCE_SCALE = - confidenceScaleFromDelta(30); + // The number of milliseconds for which the device posture must be stable + // before we perform an orientation change. If the device appears to be rotating + // (being picked up, put down) then we keep waiting until it settles. + private static final int SETTLE_TIME_MS = 200; - // Transition takes 2x longer when tilt is 60 degrees from vertical. - private static final float TILT_ANGLE_CONFIDENCE_SCALE = confidenceScaleFromDelta(60); + // The maximum change in magnitude that can occur during the settle time. + // Tuning this constant particularly helps to filter out situations where the + // device is being picked up or put down by the user. + private static final float SETTLE_MAGNITUDE_MAX_DELTA = + SensorManager.STANDARD_GRAVITY * 0.2f; - // Transition takes 2x longer when acceleration is 0.5 Gs. - private static final float MAGNITUDE_CONFIDENCE_SCALE = confidenceScaleFromDelta( - SensorManager.STANDARD_GRAVITY * 0.5f); + // The maximum change in tilt angle that can occur during the settle time. + private static final int SETTLE_TILT_ANGLE_MAX_DELTA = 5; - // The number of milliseconds for which a new orientation must be stable before - // we perform an orientation change under ideal conditions. It will take - // proportionally longer than this to effect an orientation change when - // the proposed orientation confidence is low. - private static final float ORIENTATION_SETTLE_TIME_MS = 250; - - // The confidence that we have abount effecting each orientation change. - // When one of these values exceeds 1.0, we have determined our new orientation! - private float mConfidence[] = new float[4]; + // The maximum change in orientation angle that can occur during the settle time. + private static final int SETTLE_ORIENTATION_ANGLE_MAX_DELTA = 5; public SensorEventListenerImpl(WindowOrientationListener orientationListener) { mOrientationListener = orientationListener; } - public int getCurrentRotation(int lastRotation) { - return mRotation != ROTATION_UNKNOWN ? mRotation : lastRotation; + public int getProposedRotation() { + return mProposalAgeMS >= SETTLE_TIME_MS ? mProposalRotation : -1; } @Override @@ -369,20 +367,18 @@ public abstract class WindowOrientationListener { // Reset the orientation listener state if the samples are too far apart in time // or when we see values of (0, 0, 0) which indicates that we polled the // accelerometer too soon after turning it on and we don't have any data yet. - final float timeDeltaMS = (event.timestamp - mLastTimestamp) * 0.000001f; + final long now = event.timestamp; + final float timeDeltaMS = (now - mLastTimestamp) * 0.000001f; boolean skipSample; if (timeDeltaMS <= 0 || timeDeltaMS > MAX_FILTER_DELTA_TIME_MS || (x == 0 && y == 0 && z == 0)) { if (log) { Slog.v(TAG, "Resetting orientation listener."); } - for (int i = 0; i < 4; i++) { - mConfidence[i] = 0; - } + clearProposal(); skipSample = true; } else { - final float alpha = timeDeltaMS - / (FILTER_TIME_CONSTANT_MS + timeDeltaMS) * FILTER_GAIN; + final float alpha = timeDeltaMS / (FILTER_TIME_CONSTANT_MS + timeDeltaMS); x = alpha * (x - mLastFilteredX) + mLastFilteredX; y = alpha * (y - mLastFilteredY) + mLastFilteredY; z = alpha * (z - mLastFilteredZ) + mLastFilteredZ; @@ -392,17 +388,13 @@ public abstract class WindowOrientationListener { } skipSample = false; } - mLastTimestamp = event.timestamp; + mLastTimestamp = now; mLastFilteredX = x; mLastFilteredY = y; mLastFilteredZ = z; - boolean orientationChanged = false; + final int oldProposedRotation = getProposedRotation(); if (!skipSample) { - // Determine a proposed orientation based on the currently available data. - int proposedOrientation = ROTATION_UNKNOWN; - float combinedConfidence = 1.0f; - // Calculate the magnitude of the acceleration vector. final float magnitude = (float) Math.sqrt(x * x + y * y + z * z); if (magnitude < MIN_ACCELERATION_MAGNITUDE @@ -411,6 +403,7 @@ public abstract class WindowOrientationListener { Slog.v(TAG, "Ignoring sensor data, magnitude out of range: " + "magnitude=" + magnitude); } + clearProposal(); } else { // Calculate the tilt angle. // This is the angle between the up vector and the x-y plane (the plane of @@ -418,123 +411,82 @@ public abstract class WindowOrientationListener { // -90 degrees: screen horizontal and facing the ground (overhead) // 0 degrees: screen vertical // 90 degrees: screen horizontal and facing the sky (on table) - final int tiltAngle = (int) Math.round( - Math.asin(z / magnitude) * RADIANS_TO_DEGREES); - - // If the tilt angle is too close to horizontal then we cannot determine - // the orientation angle of the screen. - if (Math.abs(tiltAngle) > MAX_TILT) { - if (log) { - Slog.v(TAG, "Ignoring sensor data, tilt angle too high: " - + "magnitude=" + magnitude + ", tiltAngle=" + tiltAngle); - } - } else { - // Calculate the orientation angle. - // This is the angle between the x-y projection of the up vector onto - // the +y-axis, increasing clockwise in a range of [0, 360] degrees. - int orientationAngle = (int) Math.round( - -Math.atan2(-x, y) * RADIANS_TO_DEGREES); - if (orientationAngle < 0) { - // atan2 returns [-180, 180]; normalize to [0, 360] - orientationAngle += 360; - } - - // Find the nearest orientation. - // An orientation of 0 can have a nearest angle of 0 or 360 depending - // on which is closer to the measured orientation angle. We leave the - // nearest angle at 360 in that case since it makes the delta calculation - // for orientation angle confidence easier below. - int nearestOrientation = (orientationAngle + 45) / 90; - int nearestOrientationAngle = nearestOrientation * 90; - if (nearestOrientation == 4) { - nearestOrientation = 0; - } - - // Determine the proposed orientation. - // The confidence of the proposal is 1.0 when it is ideal and it - // decays exponentially as the proposal moves further from the ideal - // angle, tilt and magnitude of the proposed orientation. - if (isTiltAngleAcceptable(nearestOrientation, tiltAngle) - && isOrientationAngleAcceptable(nearestOrientation, - orientationAngle)) { - proposedOrientation = nearestOrientation; - - final float idealOrientationAngle = nearestOrientationAngle; - final float orientationConfidence = confidence(orientationAngle, - idealOrientationAngle, ORIENTATION_ANGLE_CONFIDENCE_SCALE); - - final float idealTiltAngle = 0; - final float tiltConfidence = confidence(tiltAngle, - idealTiltAngle, TILT_ANGLE_CONFIDENCE_SCALE); - - final float idealMagnitude = SensorManager.STANDARD_GRAVITY; - final float magnitudeConfidence = confidence(magnitude, - idealMagnitude, MAGNITUDE_CONFIDENCE_SCALE); - - combinedConfidence = orientationConfidence - * tiltConfidence * magnitudeConfidence; - - if (log) { - Slog.v(TAG, "Proposal: " - + "magnitude=" + magnitude - + ", tiltAngle=" + tiltAngle - + ", orientationAngle=" + orientationAngle - + ", proposedOrientation=" + proposedOrientation - + ", combinedConfidence=" + combinedConfidence - + ", orientationConfidence=" + orientationConfidence - + ", tiltConfidence=" + tiltConfidence - + ", magnitudeConfidence=" + magnitudeConfidence); - } - } else { - if (log) { - Slog.v(TAG, "Ignoring sensor data, no proposal: " - + "magnitude=" + magnitude + ", tiltAngle=" + tiltAngle - + ", orientationAngle=" + orientationAngle); - } - } - } - } - - // Sum up the orientation confidence weights. - // Detect an orientation change when the sum reaches 1.0. - final float confidenceAmount = combinedConfidence * timeDeltaMS - / ORIENTATION_SETTLE_TIME_MS; - for (int i = 0; i < 4; i++) { - if (i == proposedOrientation) { - mConfidence[i] += confidenceAmount; - if (mConfidence[i] >= 1.0f) { - mConfidence[i] = 1.0f; - - if (i != mRotation) { - if (log) { - Slog.v(TAG, "Orientation changed! rotation=" + i); - } - mRotation = i; - orientationChanged = true; - } + final int tiltAngle = (int) Math.round( + Math.asin(z / magnitude) * RADIANS_TO_DEGREES); + + // If the tilt angle is too close to horizontal then we cannot determine + // the orientation angle of the screen. + if (Math.abs(tiltAngle) > MAX_TILT) { + if (log) { + Slog.v(TAG, "Ignoring sensor data, tilt angle too high: " + + "magnitude=" + magnitude + ", tiltAngle=" + tiltAngle); } + clearProposal(); } else { - mConfidence[i] -= confidenceAmount; - if (mConfidence[i] < 0.0f) { - mConfidence[i] = 0.0f; + // Calculate the orientation angle. + // This is the angle between the x-y projection of the up vector onto + // the +y-axis, increasing clockwise in a range of [0, 360] degrees. + int orientationAngle = (int) Math.round( + -Math.atan2(-x, y) * RADIANS_TO_DEGREES); + if (orientationAngle < 0) { + // atan2 returns [-180, 180]; normalize to [0, 360] + orientationAngle += 360; + } + + // Find the nearest rotation. + int nearestRotation = (orientationAngle + 45) / 90; + if (nearestRotation == 4) { + nearestRotation = 0; + } + + // Determine the proposed orientation. + // The confidence of the proposal is 1.0 when it is ideal and it + // decays exponentially as the proposal moves further from the ideal + // angle, tilt and magnitude of the proposed orientation. + if (!isTiltAngleAcceptable(nearestRotation, tiltAngle) + || !isOrientationAngleAcceptable(nearestRotation, + orientationAngle)) { + if (log) { + Slog.v(TAG, "Ignoring sensor data, no proposal: " + + "magnitude=" + magnitude + ", tiltAngle=" + tiltAngle + + ", orientationAngle=" + orientationAngle); + } + clearProposal(); + } else { + if (log) { + Slog.v(TAG, "Proposal: " + + "magnitude=" + magnitude + + ", tiltAngle=" + tiltAngle + + ", orientationAngle=" + orientationAngle + + ", proposalRotation=" + mProposalRotation); + } + updateProposal(nearestRotation, now / 1000000L, + magnitude, tiltAngle, orientationAngle); } } } } // Write final statistics about where we are in the orientation detection process. + final int proposedRotation = getProposedRotation(); if (log) { - Slog.v(TAG, "Result: rotation=" + mRotation - + ", confidence=[" - + mConfidence[0] + ", " - + mConfidence[1] + ", " - + mConfidence[2] + ", " - + mConfidence[3] + "], timeDeltaMS=" + timeDeltaMS); + final float proposalConfidence = Math.min( + mProposalAgeMS * 1.0f / SETTLE_TIME_MS, 1.0f); + Slog.v(TAG, "Result: currentRotation=" + mOrientationListener.mCurrentRotation + + ", proposedRotation=" + proposedRotation + + ", timeDeltaMS=" + timeDeltaMS + + ", proposalRotation=" + mProposalRotation + + ", proposalAgeMS=" + mProposalAgeMS + + ", proposalConfidence=" + proposalConfidence); } // Tell the listener. - if (orientationChanged) { - mOrientationListener.onOrientationChanged(mRotation); + if (proposedRotation != oldProposedRotation && proposedRotation >= 0) { + if (log) { + Slog.v(TAG, "Proposed rotation changed! proposedRotation=" + proposedRotation + + ", oldProposedRotation=" + oldProposedRotation); + } + mOrientationListener.onProposedRotationChanged(proposedRotation); } } @@ -542,33 +494,34 @@ public abstract class WindowOrientationListener { * Returns true if the tilt angle is acceptable for a proposed * orientation transition. */ - private boolean isTiltAngleAcceptable(int proposedOrientation, + private boolean isTiltAngleAcceptable(int proposedRotation, int tiltAngle) { - return tiltAngle >= TILT_TOLERANCE[proposedOrientation][0] - && tiltAngle <= TILT_TOLERANCE[proposedOrientation][1]; + return tiltAngle >= TILT_TOLERANCE[proposedRotation][0] + && tiltAngle <= TILT_TOLERANCE[proposedRotation][1]; } /** * Returns true if the orientation angle is acceptable for a proposed * orientation transition. + * * This function takes into account the gap between adjacent orientations * for hysteresis. */ - private boolean isOrientationAngleAcceptable(int proposedOrientation, - int orientationAngle) { - final int currentOrientation = mRotation; - + private boolean isOrientationAngleAcceptable(int proposedRotation, int orientationAngle) { // If there is no current rotation, then there is no gap. - if (currentOrientation != ROTATION_UNKNOWN) { - // If the proposed orientation is the same or is counter-clockwise adjacent, + // The gap is used only to introduce hysteresis among advertised orientation + // changes to avoid flapping. + final int currentRotation = mOrientationListener.mCurrentRotation; + if (currentRotation >= 0) { + // If the proposed rotation is the same or is counter-clockwise adjacent, // then we set a lower bound on the orientation angle. - // For example, if currentOrientation is ROTATION_0 and proposed is ROTATION_90, + // For example, if currentRotation is ROTATION_0 and proposed is ROTATION_90, // then we want to check orientationAngle > 45 + GAP / 2. - if (proposedOrientation == currentOrientation - || proposedOrientation == (currentOrientation + 1) % 4) { - int lowerBound = proposedOrientation * 90 - 45 + if (proposedRotation == currentRotation + || proposedRotation == (currentRotation + 1) % 4) { + int lowerBound = proposedRotation * 90 - 45 + ADJACENT_ORIENTATION_ANGLE_GAP / 2; - if (proposedOrientation == 0) { + if (proposedRotation == 0) { if (orientationAngle >= 315 && orientationAngle < lowerBound + 360) { return false; } @@ -579,15 +532,15 @@ public abstract class WindowOrientationListener { } } - // If the proposed orientation is the same or is clockwise adjacent, + // If the proposed rotation is the same or is clockwise adjacent, // then we set an upper bound on the orientation angle. - // For example, if currentOrientation is ROTATION_0 and proposed is ROTATION_270, + // For example, if currentRotation is ROTATION_0 and proposed is ROTATION_270, // then we want to check orientationAngle < 315 - GAP / 2. - if (proposedOrientation == currentOrientation - || proposedOrientation == (currentOrientation + 3) % 4) { - int upperBound = proposedOrientation * 90 + 45 + if (proposedRotation == currentRotation + || proposedRotation == (currentRotation + 3) % 4) { + int upperBound = proposedRotation * 90 + 45 - ADJACENT_ORIENTATION_ANGLE_GAP / 2; - if (proposedOrientation == 0) { + if (proposedRotation == 0) { if (orientationAngle <= 45 && orientationAngle > upperBound) { return false; } @@ -601,21 +554,58 @@ public abstract class WindowOrientationListener { return true; } - /** - * Calculate an exponentially weighted confidence value in the range [0.0, 1.0]. - * The further the value is from the target, the more the confidence trends to 0. - */ - private static float confidence(float value, float target, float scale) { - return (float) Math.exp(-Math.abs(value - target) * scale); + private void clearProposal() { + mProposalRotation = -1; + mProposalAgeMS = 0; } - /** - * Calculate a scale factor for the confidence weight exponent. - * The scale value is chosen such that confidence(value, target, scale) == 0.5 - * whenever abs(value - target) == cutoffDelta. - */ - private static float confidenceScaleFromDelta(float cutoffDelta) { - return (float) -Math.log(0.5) / cutoffDelta; + private void updateProposal(int rotation, long timestampMS, + float magnitude, int tiltAngle, int orientationAngle) { + if (mProposalRotation != rotation) { + mProposalRotation = rotation; + mHistoryIndex = 0; + mHistoryLength = 0; + } + + final int index = mHistoryIndex; + mHistoryTimestampMS[index] = timestampMS; + mHistoryMagnitudes[index] = magnitude; + mHistoryTiltAngles[index] = tiltAngle; + mHistoryOrientationAngles[index] = orientationAngle; + mHistoryIndex = (index + 1) % HISTORY_SIZE; + if (mHistoryLength < HISTORY_SIZE) { + mHistoryLength += 1; + } + + long age = 0; + for (int i = 1; i < mHistoryLength; i++) { + final int olderIndex = (index + HISTORY_SIZE - i) % HISTORY_SIZE; + if (Math.abs(mHistoryMagnitudes[olderIndex] - magnitude) + > SETTLE_MAGNITUDE_MAX_DELTA) { + break; + } + if (angleAbsoluteDelta(mHistoryTiltAngles[olderIndex], + tiltAngle) > SETTLE_TILT_ANGLE_MAX_DELTA) { + break; + } + if (angleAbsoluteDelta(mHistoryOrientationAngles[olderIndex], + orientationAngle) > SETTLE_ORIENTATION_ANGLE_MAX_DELTA) { + break; + } + age = timestampMS - mHistoryTimestampMS[olderIndex]; + if (age >= SETTLE_TIME_MS) { + break; + } + } + mProposalAgeMS = age; + } + + private static int angleAbsoluteDelta(int a, int b) { + int delta = Math.abs(a - b); + if (delta > 180) { + delta = 360 - delta; + } + return delta; } } } diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java index 01587aac7d2a..b06c112cdf54 100644 --- a/core/java/android/view/textservice/TextServicesManager.java +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -223,7 +223,7 @@ public final class TextServicesManager { try { sService.setSpellCheckerEnabled(enabled); } catch (RemoteException e) { - Log.e(TAG, "Error in setSpellCheckerSubtype:" + e); + Log.e(TAG, "Error in setSpellCheckerEnabled:" + e); } } @@ -234,7 +234,7 @@ public final class TextServicesManager { try { return sService.isSpellCheckerEnabled(); } catch (RemoteException e) { - Log.e(TAG, "Error in setSpellCheckerSubtype:" + e); + Log.e(TAG, "Error in isSpellCheckerEnabled:" + e); return false; } } diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index 309857d033e0..28f54aa08e7c 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -1159,51 +1159,49 @@ class BrowserFrame extends Handler { } /** - * Called by JNI when the native HTTPS stack gets an invalid cert chain. + * Called by JNI when the Chromium HTTP stack gets an invalid certificate chain. * * We delegate the request to CallbackProxy, and route its response to * {@link #nativeSslCertErrorProceed(int)} or * {@link #nativeSslCertErrorCancel(int, int)}. */ - private void reportSslCertError( - final int handle, final int cert_error, byte cert_der[], String url) { - final SslError ssl_error; + private void reportSslCertError(final int handle, final int certError, byte certDER[], + String url) { + final SslError sslError; try { - X509Certificate cert = new X509CertImpl(cert_der); + X509Certificate cert = new X509CertImpl(certDER); SslCertificate sslCert = new SslCertificate(cert); if (JniUtil.useChromiumHttpStack()) { - ssl_error = SslError.SslErrorFromChromiumErrorCode(cert_error, sslCert, + sslError = SslError.SslErrorFromChromiumErrorCode(certError, sslCert, new URL(url).getHost()); } else { - ssl_error = new SslError(cert_error, cert, url); + sslError = new SslError(certError, cert, url); } } catch (IOException e) { // Can't get the certificate, not much to do. Log.e(LOGTAG, "Can't get the certificate from WebKit, canceling"); - nativeSslCertErrorCancel(handle, cert_error); + nativeSslCertErrorCancel(handle, certError); return; } - SslErrorHandler handler = new SslErrorHandler() { + if (SslCertLookupTable.getInstance().isAllowed(sslError)) { + nativeSslCertErrorProceed(handle); + return; + } + SslErrorHandler handler = new SslErrorHandler() { @Override public void proceed() { - SslCertLookupTable.getInstance().Allow(ssl_error); + SslCertLookupTable.getInstance().setIsAllowed(sslError, true); nativeSslCertErrorProceed(handle); } - @Override public void cancel() { - SslCertLookupTable.getInstance().Deny(ssl_error); - nativeSslCertErrorCancel(handle, cert_error); + SslCertLookupTable.getInstance().setIsAllowed(sslError, false); + nativeSslCertErrorCancel(handle, certError); } }; - - if (SslCertLookupTable.getInstance().IsAllowed(ssl_error)) { - nativeSslCertErrorProceed(handle); - } else { - mCallbackProxy.onReceivedSslError(handler, ssl_error); - } + mCallbackProxy.onReceivedSslError(handler, sslError); } /** @@ -1416,7 +1414,7 @@ class BrowserFrame extends Handler { private native void nativeAuthenticationCancel(int handle); private native void nativeSslCertErrorProceed(int handle); - private native void nativeSslCertErrorCancel(int handle, int cert_error); + private native void nativeSslCertErrorCancel(int handle, int certError); native void nativeSslClientCert(int handle, byte[] pkcs8EncodedPrivateKey, diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index 88583df47ce3..5ee90a4fdab6 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -165,8 +165,6 @@ class CallbackProxy extends Handler { /** * Get the WebViewClient. * @return the current WebViewClient instance. - * - *@hide pending API council approval. */ public WebViewClient getWebViewClient() { return mWebViewClient; @@ -907,11 +905,9 @@ class CallbackProxy extends Handler { */ public void onPageStarted(String url, Bitmap favicon) { - // Do an unsynchronized quick check to avoid posting if no callback has - // been set. - if (mWebViewClient == null) { - return; - } + // We need to send the message even if no WebViewClient is set, because we need to call + // WebView.onPageStarted(). + // Performance probe if (PERF_PROBE) { mWebCoreThreadTime = SystemClock.currentThreadTimeMillis(); @@ -1013,10 +1009,6 @@ class CallbackProxy extends Handler { sendMessage(msg); } - /** - * @hide - hide this because it contains a parameter of type SslError. - * SslError is located in a hidden package. - */ public void onReceivedSslError(SslErrorHandler handler, SslError error) { // Do an unsynchronized quick check to avoid posting if no callback has // been set. @@ -1031,9 +1023,7 @@ class CallbackProxy extends Handler { msg.obj = map; sendMessage(msg); } - /** - * @hide - */ + public void onReceivedClientCertRequest(ClientCertRequestHandler handler, String host_and_port) { // Do an unsynchronized quick check to avoid posting if no callback has // been set. @@ -1048,17 +1038,8 @@ class CallbackProxy extends Handler { msg.obj = map; sendMessage(msg); } - /** - * @hide - hide this because it contains a parameter of type SslCertificate, - * which is located in a hidden package. - */ public void onReceivedCertificate(SslCertificate certificate) { - // Do an unsynchronized quick check to avoid posting if no callback has - // been set. - if (mWebViewClient == null) { - return; - } // here, certificate can be null (if the site is not secure) sendMessage(obtainMessage(RECEIVED_CERTIFICATE, certificate)); } diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java index 1e958549809d..3600d09732e9 100644 --- a/core/java/android/webkit/HTML5Audio.java +++ b/core/java/android/webkit/HTML5Audio.java @@ -23,6 +23,7 @@ import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnPreparedListener; import android.media.MediaPlayer.OnSeekCompleteListener; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.util.Log; @@ -33,7 +34,11 @@ import java.util.Timer; import java.util.TimerTask; /** - * <p>HTML5 support class for Audio. + * HTML5 support class for Audio. + * + * This class runs almost entirely on the WebCore thread. The exception is when + * accessing the WebView object to determine whether private browsing is + * enabled. */ class HTML5Audio extends Handler implements MediaPlayer.OnBufferingUpdateListener, @@ -49,7 +54,7 @@ class HTML5Audio extends Handler // The C++ MediaPlayerPrivateAndroid object. private int mNativePointer; // The private status of the view that created this player - private boolean mIsPrivate; + private IsPrivateBrowsingEnabledGetter mIsPrivateBrowsingEnabledGetter; private static int IDLE = 0; private static int INITIALIZED = 1; @@ -82,6 +87,35 @@ class HTML5Audio extends Handler } } + // Helper class to determine whether private browsing is enabled in the + // given WebView. Queries the WebView on the UI thread. Calls to get() + // block until the data is available. + private class IsPrivateBrowsingEnabledGetter { + private boolean mIsReady; + private boolean mIsPrivateBrowsingEnabled; + IsPrivateBrowsingEnabledGetter(Looper uiThreadLooper, final WebView webView) { + new Handler(uiThreadLooper).post(new Runnable() { + @Override + public void run() { + synchronized(IsPrivateBrowsingEnabledGetter.this) { + mIsPrivateBrowsingEnabled = webView.isPrivateBrowsingEnabled(); + mIsReady = true; + IsPrivateBrowsingEnabledGetter.this.notify(); + } + } + }); + } + synchronized boolean get() { + while (!mIsReady) { + try { + wait(); + } catch (InterruptedException e) { + } + } + return mIsPrivateBrowsingEnabled; + } + }; + @Override public void handleMessage(Message msg) { switch (msg.what) { @@ -149,7 +183,8 @@ class HTML5Audio extends Handler // Save the native ptr mNativePointer = nativePtr; resetMediaPlayer(); - mIsPrivate = webViewCore.getWebView().isPrivateBrowsingEnabled(); + mIsPrivateBrowsingEnabledGetter = new IsPrivateBrowsingEnabledGetter( + webViewCore.getContext().getMainLooper(), webViewCore.getWebView()); } private void resetMediaPlayer() { @@ -177,13 +212,14 @@ class HTML5Audio extends Handler if (mState != IDLE) { resetMediaPlayer(); } - String cookieValue = CookieManager.getInstance().getCookie(url, mIsPrivate); + String cookieValue = CookieManager.getInstance().getCookie( + url, mIsPrivateBrowsingEnabledGetter.get()); Map<String, String> headers = new HashMap<String, String>(); if (cookieValue != null) { headers.put(COOKIE, cookieValue); } - if (mIsPrivate) { + if (mIsPrivateBrowsingEnabledGetter.get()) { headers.put(HIDE_URL_LOGS, "true"); } diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java index 97dc2918a2c9..42581c2fa51d 100644 --- a/core/java/android/webkit/HTML5VideoInline.java +++ b/core/java/android/webkit/HTML5VideoInline.java @@ -1,6 +1,8 @@ package android.webkit; +import android.Manifest.permission; +import android.content.pm.PackageManager; import android.graphics.SurfaceTexture; import android.media.MediaPlayer; import android.webkit.HTML5VideoView; @@ -52,7 +54,12 @@ public class HTML5VideoInline extends HTML5VideoView{ public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) { super.prepareDataAndDisplayMode(proxy); setFrameAvailableListener(proxy); - mPlayer.setWakeMode(proxy.getContext(), PowerManager.FULL_WAKE_LOCK); + // TODO: This is a workaround, after b/5375681 fixed, we should switch + // to the better way. + if (mProxy.getContext().checkCallingOrSelfPermission(permission.WAKE_LOCK) + == PackageManager.PERMISSION_GRANTED) { + mPlayer.setWakeMode(proxy.getContext(), PowerManager.FULL_WAKE_LOCK); + } } // Pause the play and update the play/pause button diff --git a/core/java/android/webkit/SslCertLookupTable.java b/core/java/android/webkit/SslCertLookupTable.java index faff110aae8a..052244f95f89 100644 --- a/core/java/android/webkit/SslCertLookupTable.java +++ b/core/java/android/webkit/SslCertLookupTable.java @@ -20,14 +20,15 @@ import android.os.Bundle; import android.net.http.SslError; /** - * A simple class to store the wrong certificates that user is aware but - * chose to proceed. + * Stores the user's decision of whether to allow or deny an invalid certificate. + * + * This class is not threadsafe. It is used only on the WebCore thread. */ final class SslCertLookupTable { private static SslCertLookupTable sTable; private final Bundle table; - public static synchronized SslCertLookupTable getInstance() { + public static SslCertLookupTable getInstance() { if (sTable == null) { sTable = new SslCertLookupTable(); } @@ -38,15 +39,15 @@ final class SslCertLookupTable { table = new Bundle(); } - public void Allow(SslError ssl_error) { - table.putBoolean(ssl_error.toString(), true); + public void setIsAllowed(SslError sslError, boolean allow) { + table.putBoolean(sslError.toString(), allow); } - public void Deny(SslError ssl_error) { - table.putBoolean(ssl_error.toString(), false); + public boolean isAllowed(SslError sslError) { + return table.getBoolean(sslError.toString()); } - public boolean IsAllowed(SslError ssl_error) { - return table.getBoolean(ssl_error.toString()); + public void clear() { + table.clear(); } } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 122a717f7643..370cce40b704 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1808,6 +1808,8 @@ public class WebView extends AbsoluteLayout /** * Restore the display data that was save in {@link #savePicture}. Used in * conjunction with {@link #restoreState}. + * + * Note that this will not work if the WebView is hardware accelerated. * @param b A Bundle containing the saved display data. * @param src The file where the picture data was stored. * @return True if the picture was successfully restored. @@ -2390,6 +2392,12 @@ public class WebView extends AbsoluteLayout return mZoomManager.getScale(); } + // Called by JNI. Returns the scale to apply to the text selection handles + /* package */ float getTextHandleScale() { + float density = mContext.getResources().getDisplayMetrics().density; + return density / getScale(); + } + /** * Return the reading level scale of the WebView * @return The reading level scale. @@ -4300,6 +4308,7 @@ public class WebView extends AbsoluteLayout selectionDone(); } mOrientation = newConfig.orientation; + mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT); } /** @@ -7170,6 +7179,14 @@ public class WebView extends AbsoluteLayout } /** + * Return the overview scale of the WebView + * @return The overview scale. + */ + float getZoomOverviewScale() { + return mZoomManager.getZoomOverviewScale(); + } + + /** * @return TRUE if the WebView can be zoomed in. */ public boolean canZoomIn() { @@ -9272,13 +9289,13 @@ public class WebView extends AbsoluteLayout private static void checkThread() { if (Looper.myLooper() != Looper.getMainLooper()) { - RuntimeException exception = new RuntimeException( - "A WebView method was called on thread '" + + Throwable throwable = new Throwable( + "Warning: A WebView method was called on thread '" + Thread.currentThread().getName() + "'. " + "All WebView methods must be called on the UI thread. " + "Future versions of WebView may not support use on other threads."); - Log.e(LOGTAG, Log.getStackTraceString(exception)); - StrictMode.onWebViewMethodCalledOnWrongThread(exception); + Log.w(LOGTAG, Log.getStackTraceString(throwable)); + StrictMode.onWebViewMethodCalledOnWrongThread(throwable); } } diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 48359d44daca..63c4d032ddab 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -1349,8 +1349,14 @@ public final class WebViewCore { } case CLEAR_SSL_PREF_TABLE: - Network.getInstance(mContext) - .clearUserSslPrefTable(); + if (JniUtil.useChromiumHttpStack()) { + // FIXME: This will not work for connections currently in use, as + // they cache the certificate responses. See http://b/5324235. + SslCertLookupTable.getInstance().clear(); + nativeCloseIdleConnections(); + } else { + Network.getInstance(mContext).clearUserSslPrefTable(); + } break; case TOUCH_UP: @@ -2225,6 +2231,8 @@ public final class WebViewCore { mRepaintScheduled = false; } + // Gets the WebView corresponding to this WebViewCore. Note that the + // WebView object must only be used on the UI thread. /* package */ WebView getWebView() { return mWebView; } @@ -2512,10 +2520,13 @@ public final class WebViewCore { // called by JNI private void restoreScale(float scale, float textWrapScale) { if (mBrowserFrame.firstLayoutDone() == false) { - final float defaultScale = mWebView.getDefaultZoomScale(); - mRestoredScale = (scale <= 0.0) ? defaultScale : scale; + // If restored scale and textWrapScale are 0, set them to + // overview and reading level scale respectively. + mRestoredScale = (scale <= 0.0) + ? mWebView.getZoomOverviewScale() : scale; if (mSettings.getUseWideViewPort()) { - mRestoredTextWrapScale = (textWrapScale <= 0.0) ? defaultScale : textWrapScale; + mRestoredTextWrapScale = (textWrapScale <= 0.0) + ? mWebView.getReadingLevelScale() : textWrapScale; } } } @@ -2623,8 +2634,7 @@ public final class WebViewCore { } } - // called by JNI - private Context getContext() { + Context getContext() { return mContext; } diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index 7ca6aeba87fe..7f526e7e7c1b 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -1128,12 +1128,6 @@ class ZoomManager { mTextWrapScale = Math.max(mTextWrapScale, overviewScale); } reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale); - } else { - // In case of restored scale, treat defaultScale as overview since - // it usually means the previous scale is not saved. - if (scale == mDefaultScale && settings.getLoadWithOverviewMode()) { - scale = overviewScale; - } } mInitialZoomOverview = settings.getLoadWithOverviewMode() && !exceedsMinScaleIncrement(scale, overviewScale); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index ba89ef3e6cbd..7b8c7f218ddc 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -1304,16 +1304,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - // Do not append text content to scroll events they are fired frequently - // and the client has already received another event type with the text. - if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) { - super.dispatchPopulateAccessibilityEvent(event); - } - return false; - } - /** * Indicates whether the children's drawing cache is used during a scroll. * By default, the drawing cache is enabled but this will consume more memory. diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java index 25af3fa0e85a..c37cc5223830 100644 --- a/core/java/android/widget/ActivityChooserView.java +++ b/core/java/android/widget/ActivityChooserView.java @@ -16,6 +16,8 @@ package android.widget; +import com.android.internal.R; + import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -25,6 +27,7 @@ import android.content.res.TypedArray; import android.database.DataSetObserver; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.ActionProvider; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -32,8 +35,6 @@ import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.ActivityChooserModel.ActivityChooserModelClient; -import com.android.internal.R; - /** * This class is a view for choosing an activity for handling a given {@link Intent}. * <p> @@ -105,6 +106,11 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod private final int mListPopupMaxWidth; /** + * The ActionProvider hosting this view, if applicable. + */ + ActionProvider mProvider; + + /** * Observer for the model data. */ private final DataSetObserver mModelDataSetOberver = new DataSetObserver() { @@ -129,6 +135,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod getListPopupWindow().dismiss(); } else { getListPopupWindow().show(); + if (mProvider != null) { + mProvider.subUiVisibilityChanged(true); + } } } } @@ -260,6 +269,14 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod } /** + * Set the provider hosting this view, if applicable. + * @hide Internal use only + */ + public void setProvider(ActionProvider provider) { + mProvider = provider; + } + + /** * Shows the popup window with activities. * * @return True if the popup was shown, false if already showing. @@ -285,20 +302,22 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener); - mAdapter.setMaxActivityCount(maxActivityCount); + final boolean defaultActivityButtonShown = + mDefaultActivityButton.getVisibility() == VISIBLE; final int activityCount = mAdapter.getActivityCount(); + final int maxActivityCountOffset = defaultActivityButtonShown ? 1 : 0; if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED - && activityCount > maxActivityCount + 1) { + && activityCount > maxActivityCount + maxActivityCountOffset) { mAdapter.setShowFooterView(true); + mAdapter.setMaxActivityCount(maxActivityCount - 1); } else { mAdapter.setShowFooterView(false); + mAdapter.setMaxActivityCount(maxActivityCount); } ListPopupWindow popupWindow = getListPopupWindow(); if (!popupWindow.isShowing()) { - final boolean defaultActivityButtonShown = - mDefaultActivityButton.getVisibility() == VISIBLE; if (mIsSelectingDefaultActivity || !defaultActivityButtonShown) { mAdapter.setShowDefaultActivity(true, defaultActivityButtonShown); } else { @@ -307,6 +326,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth); popupWindow.setContentWidth(contentWidth); popupWindow.show(); + if (mProvider != null) { + mProvider.subUiVisibilityChanged(true); + } } } @@ -525,6 +547,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod // PopUpWindow.OnDismissListener#onDismiss public void onDismiss() { notifyOnDismissListener(); + if (mProvider != null) { + mProvider.subUiVisibilityChanged(false); + } } private void notifyOnDismissListener() { diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java index 5392c2e5f5ad..a4b4e783def9 100644 --- a/core/java/android/widget/AdapterView.java +++ b/core/java/android/widget/AdapterView.java @@ -881,31 +881,30 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { @Override public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - // This is an exceptional case which occurs when a window gets the - // focus and sends a focus event via its focused child to announce - // current focus/selection. AdapterView fires selection but not focus - // events so we change the event type here. - if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) { - event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED); + final int eventType = event.getEventType(); + switch (eventType) { + case AccessibilityEvent.TYPE_VIEW_SCROLLED: + // Do not populate the text of scroll events. + return true; + case AccessibilityEvent.TYPE_VIEW_FOCUSED: + // This is an exceptional case which occurs when a window gets the + // focus and sends a focus event via its focused child to announce + // current focus/selection. AdapterView fires selection but not focus + // events so we change the event type here. + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) { + event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED); + } + break; } View selectedView = getSelectedView(); if (selectedView != null && selectedView.getVisibility() == VISIBLE) { - // We first get a chance to populate the event. - onPopulateAccessibilityEvent(event); + getSelectedView().dispatchPopulateAccessibilityEvent(event); } return false; } @Override - public void onPopulateAccessibilityEvent(AccessibilityEvent event) { - super.onPopulateAccessibilityEvent(event); - // We send selection events only from AdapterView to avoid - // generation of such event for each child. - getSelectedView().dispatchPopulateAccessibilityEvent(event); - } - - @Override public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { if (super.onRequestSendAccessibilityEvent(child, event)) { // Add a record for ourselves as well. diff --git a/core/java/android/widget/BaseAdapter.java b/core/java/android/widget/BaseAdapter.java index 532fd766ec66..401fcb83499d 100644 --- a/core/java/android/widget/BaseAdapter.java +++ b/core/java/android/widget/BaseAdapter.java @@ -43,13 +43,18 @@ public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { } /** - * Notifies the attached View that the underlying data has been changed - * and it should refresh itself. + * Notifies the attached observers that the underlying data has been changed + * and any View reflecting the data set should refresh itself. */ public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); } - + + /** + * Notifies the attached observers that the underlying data is no longer valid + * or available. Once invoked this adapter is no longer valid and should + * not report further data set changes. + */ public void notifyDataSetInvalidated() { mDataSetObservable.notifyInvalidated(); } diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index ba692885a768..fb9047b35b28 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -850,32 +850,65 @@ public class GridLayout extends ViewGroup { return c.getVisibility() == View.GONE; } - private void measureChildWithMargins(View child, int widthMeasureSpec, int heightMeasureSpec) { - LayoutParams lp = getLayoutParams(child); - int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, - mPaddingLeft + mPaddingRight + getTotalMargin(child, true), lp.width); - int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, - mPaddingTop + mPaddingBottom + getTotalMargin(child, false), lp.height); - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + private void measureChildWithMargins2(View child, int parentWidthSpec, int parentHeightSpec, + int childWidth, int childHeight) { + int childWidthSpec = getChildMeasureSpec(parentWidthSpec, + mPaddingLeft + mPaddingRight + getTotalMargin(child, true), childWidth); + int childHeightSpec = getChildMeasureSpec(parentHeightSpec, + mPaddingTop + mPaddingBottom + getTotalMargin(child, false), childHeight); + child.measure(childWidthSpec, childHeightSpec); } - private void measureChildrenWithMargins(int widthMeasureSpec, int heightMeasureSpec) { + private void measureChildrenWithMargins(int widthSpec, int heightSpec, boolean firstPass) { for (int i = 0, N = getChildCount(); i < N; i++) { View c = getChildAt(i); if (isGone(c)) continue; - measureChildWithMargins(c, widthMeasureSpec, heightMeasureSpec); + LayoutParams lp = getLayoutParams(c); + if (firstPass) { + measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, lp.height); + } else { + Spec spec = (orientation == HORIZONTAL) ? lp.columnSpec : lp.rowSpec; + if (spec.alignment == FILL) { + Interval span = spec.span; + Axis axis = (orientation == HORIZONTAL) ? horizontalAxis : verticalAxis; + int[] locations = axis.getLocations(); + int size = locations[span.max] - locations[span.min]; + if (orientation == HORIZONTAL) { + measureChildWithMargins2(c, widthSpec, heightSpec, size, lp.height); + } else { + measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, size); + } + } + } } } @Override protected void onMeasure(int widthSpec, int heightSpec) { - measureChildrenWithMargins(widthSpec, heightSpec); + /** If we have been called by {@link View#measure(int, int)}, one of width or height + * is likely to have changed. We must invalidate if so. */ + invalidateValues(); + + measureChildrenWithMargins(widthSpec, heightSpec, true); + + int width, height; + + // Use the orientation property to decide which axis should be laid out first. + if (orientation == HORIZONTAL) { + width = horizontalAxis.getMeasure(widthSpec); + measureChildrenWithMargins(widthSpec, heightSpec, false); + height = verticalAxis.getMeasure(heightSpec); + } else { + height = verticalAxis.getMeasure(heightSpec); + measureChildrenWithMargins(widthSpec, heightSpec, false); + width = horizontalAxis.getMeasure(widthSpec); + } - int width = getPaddingLeft() + horizontalAxis.getMeasure(widthSpec) + getPaddingRight(); - int height = getPaddingTop() + verticalAxis.getMeasure(heightSpec) + getPaddingBottom(); + int hPadding = getPaddingLeft() + getPaddingRight(); + int vPadding = getPaddingTop() + getPaddingBottom(); - int measuredWidth = Math.max(width, getSuggestedMinimumWidth()); - int measuredHeight = Math.max(height, getSuggestedMinimumHeight()); + int measuredWidth = Math.max(hPadding + width, getSuggestedMinimumWidth()); + int measuredHeight = Math.max(vPadding + height, getSuggestedMinimumHeight()); setMeasuredDimension( resolveSizeAndState(measuredWidth, widthSpec, 0), @@ -1015,8 +1048,6 @@ public class GridLayout extends ViewGroup { for the vertical one. */ final class Axis { - private static final int MIN_VALUE = -1000000; - private static final int NEW = 0; private static final int PENDING = 1; private static final int COMPLETE = 2; @@ -1024,7 +1055,7 @@ public class GridLayout extends ViewGroup { public final boolean horizontal; public int definedCount = UNDEFINED; - private int inferredCount = UNDEFINED; + private int maxIndex = UNDEFINED; PackedMap<Spec, Bounds> groupBounds; public boolean groupBoundsValid = false; @@ -1056,28 +1087,29 @@ public class GridLayout extends ViewGroup { this.horizontal = horizontal; } - private int maxIndex() { - // note the number Integer.MIN_VALUE + 1 comes up in undefined cells - int count = -1; + private int calculateMaxIndex() { + // the number Integer.MIN_VALUE + 1 comes up in undefined cells + int result = -1; for (int i = 0, N = getChildCount(); i < N; i++) { View c = getChildAt(i); LayoutParams params = getLayoutParams(c); Spec spec = horizontal ? params.columnSpec : params.rowSpec; - count = max(count, spec.span.min); - count = max(count, spec.span.max); + Interval span = spec.span; + result = max(result, span.min); + result = max(result, span.max); } - return count == -1 ? UNDEFINED : count; + return result == -1 ? UNDEFINED : result; } - private int getInferredCount() { - if (inferredCount == UNDEFINED) { - inferredCount = max(0, maxIndex()); // if there are no cells, actual count is zero + private int getMaxIndex() { + if (maxIndex == UNDEFINED) { + maxIndex = max(0, calculateMaxIndex()); // use zero when there are no children } - return inferredCount; + return maxIndex; } public int getCount() { - return max(definedCount, getInferredCount()); + return max(definedCount, getMaxIndex()); } public void setCount(int count) { @@ -1179,7 +1211,7 @@ public class GridLayout extends ViewGroup { } private void include(List<Arc> arcs, Interval key, MutableInt size, - boolean ignoreIfAlreadyPresent) { + boolean ignoreIfAlreadyPresent) { /* Remove self referential links. These appear: @@ -1341,19 +1373,18 @@ public class GridLayout extends ViewGroup { } private void init(int[] locations) { - Arrays.fill(locations, MIN_VALUE); - locations[0] = 0; + Arrays.fill(locations, 0); } private String arcsToString(List<Arc> arcs) { - String var = horizontal ? "c" : "r"; + String var = horizontal ? "x" : "y"; StringBuilder result = new StringBuilder(); - boolean first = false; - for(Arc arc : arcs) { - if (!first) { - first = true; + boolean first = true; + for (Arc arc : arcs) { + if (first) { + first = false; } else { - result =result.append(", "); + result = result.append(", "); } int src = arc.span.min; int dst = arc.span.max; @@ -1434,10 +1465,6 @@ public class GridLayout extends ViewGroup { if (originalCulprits != null) { logError(axisName, arcs, originalCulprits); } - if (DEBUG) { - Log.v(TAG, axisName + " iteration completed in " + - (1 + i) + " steps of " + N); - } return; } } @@ -1506,6 +1533,18 @@ public class GridLayout extends ViewGroup { private void computeLocations(int[] a) { solve(getArcs(), a); + if (!orderPreserved) { + // Solve returns the smallest solution to the constraint system for which all + // values are positive. One value is therefore zero - though if the row/col + // order is not preserved this may not be the first vertex. For consistency, + // translate all the values so that they measure the distance from a[0]; the + // leading edge of the parent. After this transformation some values may be + // negative. + int a0 = a[0]; + for (int i = 0, N = a.length; i < N; i++) { + a[i] = a[i] - a0; + } + } } public int[] getLocations() { @@ -1521,7 +1560,10 @@ public class GridLayout extends ViewGroup { } private int size(int[] locations) { - return max2(locations, 0) - locations[0]; + // The parental edges are attached to vertices 0 and N - even when order is not + // being preserved and other vertices fall outside this range. Measure the distance + // between vertices 0 and N, assuming that locations[0] = 0. + return locations[getCount()]; } private void setParentConstraints(int min, int max) { @@ -1561,7 +1603,7 @@ public class GridLayout extends ViewGroup { } public void invalidateStructure() { - inferredCount = UNDEFINED; + maxIndex = UNDEFINED; groupBounds = null; forwardLinks = null; @@ -2139,8 +2181,8 @@ public class GridLayout extends ViewGroup { /** * A Spec defines the horizontal or vertical characteristics of a group of - * cells. Each spec. defines the <em>grid indices</em>, <em>alignment</em> and - * <em>flexibility</em> along the appropriate axis. + * cells. Each spec. defines the <em>grid indices</em> and <em>alignment</em> + * along the appropriate axis. * <p> * The <em>grid indices</em> are the leading and trailing edges of this cell group. * See {@link GridLayout} for a description of the conventions used by GridLayout @@ -2149,6 +2191,15 @@ public class GridLayout extends ViewGroup { * The <em>alignment</em> property specifies how cells should be aligned in this group. * For row groups, this specifies the vertical alignment. * For column groups, this specifies the horizontal alignment. + * <p> + * Use the following static methods to create specs: + * <ul> + * <li>{@link #spec(int)}</li> + * <li>{@link #spec(int, int)}</li> + * <li>{@link #spec(int, Alignment)}</li> + * <li>{@link #spec(int, int, Alignment)}</li> + * </ul> + * */ public static class Spec { static final Spec UNDEFINED = spec(GridLayout.UNDEFINED); diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 9ce8fe077582..1bbc50152a8d 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -569,7 +569,7 @@ public class HorizontalScrollView extends FrameLayout { final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0); - if (canOverscroll && overScrollBy(deltaX, 0, mScrollX, 0, range, 0, + if (overScrollBy(deltaX, 0, mScrollX, 0, range, 0, mOverscrollDistance, 0, true)) { // Break our velocity if we hit a scroll barrier. mVelocityTracker.clear(); @@ -602,16 +602,12 @@ public class HorizontalScrollView extends FrameLayout { velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId); - final int right = getScrollRange(); - final int overscrollMode = getOverScrollMode(); - final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || - (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && right > 0); - - if (getChildCount() > 0 && canOverscroll) { + if (getChildCount() > 0) { if ((Math.abs(initialVelocity) > mMinimumVelocity)) { fling(-initialVelocity); } else { - if (mScroller.springBack(mScrollX, mScrollY, 0, right, 0, 0)) { + if (mScroller.springBack(mScrollX, mScrollY, 0, + getScrollRange(), 0, 0)) { invalidate(); } } diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index a63b8c887e4f..f2ea3fc1d6d2 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -75,6 +75,7 @@ public class MediaController extends FrameLayout { private WindowManager mWindowManager; private Window mWindow; private View mDecor; + private WindowManager.LayoutParams mDecorLayoutParams; private ProgressBar mProgress; private TextView mEndTime, mCurrentTime; private boolean mShowing; @@ -112,14 +113,12 @@ public class MediaController extends FrameLayout { super(context); mContext = context; mUseFastForward = useFastForward; + initFloatingWindowLayout(); initFloatingWindow(); } public MediaController(Context context) { - super(context); - mContext = context; - mUseFastForward = true; - initFloatingWindow(); + this(context, true); } private void initFloatingWindow() { @@ -142,6 +141,48 @@ public class MediaController extends FrameLayout { requestFocus(); } + // Allocate and initialize the static parts of mDecorLayoutParams. Must + // also call updateFloatingWindowLayout() to fill in the dynamic parts + // (y and width) before mDecorLayoutParams can be used. + private void initFloatingWindowLayout() { + mDecorLayoutParams = new WindowManager.LayoutParams(); + WindowManager.LayoutParams p = mDecorLayoutParams; + p.gravity = Gravity.TOP; + p.height = LayoutParams.WRAP_CONTENT; + p.x = 0; + p.format = PixelFormat.TRANSLUCENT; + p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; + p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; + p.token = null; + p.windowAnimations = 0; // android.R.style.DropDownAnimationDown; + } + + // Update the dynamic parts of mDecorLayoutParams + // Must be called with mAnchor != NULL. + private void updateFloatingWindowLayout() { + int [] anchorPos = new int[2]; + mAnchor.getLocationOnScreen(anchorPos); + + WindowManager.LayoutParams p = mDecorLayoutParams; + p.width = mAnchor.getWidth(); + p.y = anchorPos[1] + mAnchor.getHeight(); + } + + // This is called whenever mAnchor's layout bound changes + private OnLayoutChangeListener mLayoutChangeListener = + new OnLayoutChangeListener() { + public void onLayoutChange(View v, int left, int top, int right, + int bottom, int oldLeft, int oldTop, int oldRight, + int oldBottom) { + updateFloatingWindowLayout(); + if (mShowing) { + mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams); + } + } + }; + private OnTouchListener mTouchListener = new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { @@ -164,7 +205,13 @@ public class MediaController extends FrameLayout { * @param view The view to which to anchor the controller when it is visible. */ public void setAnchorView(View view) { + if (mAnchor != null) { + mAnchor.removeOnLayoutChangeListener(mLayoutChangeListener); + } mAnchor = view; + if (mAnchor != null) { + mAnchor.addOnLayoutChangeListener(mLayoutChangeListener); + } FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, @@ -279,31 +326,14 @@ public class MediaController extends FrameLayout { * the controller until hide() is called. */ public void show(int timeout) { - if (!mShowing && mAnchor != null) { setProgress(); if (mPauseButton != null) { mPauseButton.requestFocus(); } disableUnsupportedButtons(); - - int [] anchorpos = new int[2]; - mAnchor.getLocationOnScreen(anchorpos); - - WindowManager.LayoutParams p = new WindowManager.LayoutParams(); - p.gravity = Gravity.TOP; - p.width = mAnchor.getWidth(); - p.height = LayoutParams.WRAP_CONTENT; - p.x = 0; - p.y = anchorpos[1] + mAnchor.getHeight() - p.height; - p.format = PixelFormat.TRANSLUCENT; - p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; - p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; - p.token = null; - p.windowAnimations = 0; // android.R.style.DropDownAnimationDown; - mWindowManager.addView(mDecor, p); + updateFloatingWindowLayout(); + mWindowManager.addView(mDecor, mDecorLayoutParams); mShowing = true; } updatePausePlay(); diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 5345fa4d722b..b4c844b121f9 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -16,13 +16,10 @@ package android.widget; -import com.android.internal.R; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; import android.annotation.Widget; import android.content.Context; import android.content.res.ColorStateList; @@ -30,8 +27,8 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Rect; import android.graphics.Paint.Align; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.InputFilter; import android.text.InputType; @@ -43,16 +40,18 @@ import android.util.SparseArray; import android.util.TypedValue; import android.view.KeyEvent; import android.view.LayoutInflater; +import android.view.LayoutInflater.Filter; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; -import android.view.LayoutInflater.Filter; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.InputMethodManager; +import com.android.internal.R; + /** * A widget that enables the user to select a number form a predefined range. * The widget presents an input filed and up and down buttons for selecting the @@ -91,6 +90,12 @@ public class NumberPicker extends LinearLayout { private static final int SELECTOR_ADJUSTMENT_DURATION_MILLIS = 800; /** + * The duration of scrolling to the next/previous value while changing + * the current value by one, i.e. increment or decrement. + */ + private static final int CHANGE_CURRENT_BY_ONE_SCROLL_DURATION = 300; + + /** * The the delay for showing the input controls after a single tap on the * input text. */ @@ -98,24 +103,59 @@ public class NumberPicker extends LinearLayout { .getDoubleTapTimeout(); /** - * The update step for incrementing the current value. + * The strength of fading in the top and bottom while drawing the selector. */ - private static final int UPDATE_STEP_INCREMENT = 1; + private static final float TOP_AND_BOTTOM_FADING_EDGE_STRENGTH = 0.9f; /** - * The update step for decrementing the current value. + * The default unscaled height of the selection divider. */ - private static final int UPDATE_STEP_DECREMENT = -1; + private static final int UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT = 2; /** - * The strength of fading in the top and bottom while drawing the selector. + * In this state the selector wheel is not shown. */ - private static final float TOP_AND_BOTTOM_FADING_EDGE_STRENGTH = 0.9f; + private static final int SELECTOR_WHEEL_STATE_NONE = 0; /** - * The default unscaled height of the selection divider. + * In this state the selector wheel is small. + */ + private static final int SELECTOR_WHEEL_STATE_SMALL = 1; + + /** + * In this state the selector wheel is large. + */ + private static final int SELECTOR_WHEEL_STATE_LARGE = 2; + + /** + * The alpha of the selector wheel when it is bright. */ - private final int UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT = 2; + private static final int SELECTOR_WHEEL_BRIGHT_ALPHA = 255; + + /** + * The alpha of the selector wheel when it is dimmed. + */ + private static final int SELECTOR_WHEEL_DIM_ALPHA = 60; + + /** + * The alpha for the increment/decrement button when it is transparent. + */ + private static final int BUTTON_ALPHA_TRANSPARENT = 0; + + /** + * The alpha for the increment/decrement button when it is opaque. + */ + private static final int BUTTON_ALPHA_OPAQUE = 1; + + /** + * The property for setting the selector paint. + */ + private static final String PROPERTY_SELECTOR_PAINT_ALPHA = "selectorPaintAlpha"; + + /** + * The property for setting the increment/decrement button alpha. + */ + private static final String PROPERTY_BUTTON_ALPHA = "alpha"; /** * The numbers accepted by the input text's {@link Filter} @@ -168,6 +208,11 @@ public class NumberPicker extends LinearLayout { private final int mTextSize; /** + * The height of the gap between text elements if the selector wheel. + */ + private int mSelectorTextGapHeight; + + /** * The values to be displayed instead the indices. */ private String[] mDisplayedValues; @@ -223,7 +268,7 @@ public class NumberPicker extends LinearLayout { /** * The {@link Paint} for drawing the selector. */ - private final Paint mSelectorPaint; + private final Paint mSelectorWheelPaint; /** * The height of a selector element (text + gap). @@ -266,10 +311,10 @@ public class NumberPicker extends LinearLayout { private AdjustScrollerCommand mAdjustScrollerCommand; /** - * Handle to the reusable command for updating the current value from long - * press. + * Handle to the reusable command for changing the current value from long + * press by one. */ - private UpdateValueFromLongPressCommand mUpdateFromLongPressCommand; + private ChangeCurrentByOneFromLongPressCommand mChangeCurrentByOneFromLongPressCommand; /** * {@link Animator} for showing the up/down arrows. @@ -277,6 +322,11 @@ public class NumberPicker extends LinearLayout { private final AnimatorSet mShowInputControlsAnimator; /** + * {@link Animator} for dimming the selector wheel. + */ + private final Animator mDimSelectorWheelAnimator; + + /** * The Y position of the last down event. */ private float mLastDownEventY; @@ -297,9 +347,9 @@ public class NumberPicker extends LinearLayout { private boolean mAdjustScrollerOnUpEvent; /** - * Flag if to draw the selector wheel. + * The state of the selector wheel. */ - private boolean mDrawSelectorWheel; + private int mSelectorWheelState; /** * Determines speed during touch scrolling. @@ -362,6 +412,11 @@ public class NumberPicker extends LinearLayout { private final long mShowInputControlsAnimimationDuration; /** + * Flag whether the scoll wheel and the fading edges have been initialized. + */ + private boolean mScrollWheelAndFadingEdgesInitialized; + + /** * Interface to listen for changes of the current value. */ public interface OnValueChangeListener { @@ -473,7 +528,7 @@ public class NumberPicker extends LinearLayout { // the fading edge effect implemented by View and we need our // draw() method to be called. Therefore, we declare we will draw. setWillNotDraw(false); - setDrawScrollWheel(false); + setSelectorWheelState(SELECTOR_WHEEL_STATE_NONE); LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); @@ -483,9 +538,9 @@ public class NumberPicker extends LinearLayout { public void onClick(View v) { mInputText.clearFocus(); if (v.getId() == R.id.increment) { - changeCurrent(mValue + 1); + changeCurrentByOne(true); } else { - changeCurrent(mValue - 1); + changeCurrentByOne(false); } } }; @@ -494,9 +549,9 @@ public class NumberPicker extends LinearLayout { public boolean onLongClick(View v) { mInputText.clearFocus(); if (v.getId() == R.id.increment) { - postUpdateValueFromLongPress(UPDATE_STEP_INCREMENT); + postChangeCurrentByOneFromLongPress(true); } else { - postUpdateValueFromLongPress(UPDATE_STEP_DECREMENT); + postChangeCurrentByOneFromLongPress(false); } return true; } @@ -516,10 +571,17 @@ public class NumberPicker extends LinearLayout { mInputText = (EditText) findViewById(R.id.numberpicker_input); mInputText.setOnFocusChangeListener(new OnFocusChangeListener() { public void onFocusChange(View v, boolean hasFocus) { + InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); if (hasFocus) { mInputText.selectAll(); + if (inputMethodManager != null) { + inputMethodManager.showSoftInput(mInputText, 0); + } } else { mInputText.setSelection(0, 0); + if (inputMethodManager != null) { + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); + } validateInputTextView(v); } } @@ -548,16 +610,17 @@ public class NumberPicker extends LinearLayout { ColorStateList colors = mInputText.getTextColors(); int color = colors.getColorForState(ENABLED_STATE_SET, Color.WHITE); paint.setColor(color); - mSelectorPaint = paint; + mSelectorWheelPaint = paint; // create the animator for showing the input controls - final ValueAnimator fadeScroller = ObjectAnimator.ofInt(this, "selectorPaintAlpha", 255, 0); + mDimSelectorWheelAnimator = ObjectAnimator.ofInt(this, PROPERTY_SELECTOR_PAINT_ALPHA, + SELECTOR_WHEEL_BRIGHT_ALPHA, SELECTOR_WHEEL_DIM_ALPHA); final ObjectAnimator showIncrementButton = ObjectAnimator.ofFloat(mIncrementButton, - "alpha", 0, 1); + PROPERTY_BUTTON_ALPHA, BUTTON_ALPHA_TRANSPARENT, BUTTON_ALPHA_OPAQUE); final ObjectAnimator showDecrementButton = ObjectAnimator.ofFloat(mDecrementButton, - "alpha", 0, 1); + PROPERTY_BUTTON_ALPHA, BUTTON_ALPHA_TRANSPARENT, BUTTON_ALPHA_OPAQUE); mShowInputControlsAnimator = new AnimatorSet(); - mShowInputControlsAnimator.playTogether(fadeScroller, showIncrementButton, + mShowInputControlsAnimator.playTogether(mDimSelectorWheelAnimator, showIncrementButton, showDecrementButton); mShowInputControlsAnimator.addListener(new AnimatorListenerAdapter() { private boolean mCanceled = false; @@ -566,11 +629,9 @@ public class NumberPicker extends LinearLayout { public void onAnimationEnd(Animator animation) { if (!mCanceled) { // if canceled => we still want the wheel drawn - setDrawScrollWheel(false); + setSelectorWheelState(SELECTOR_WHEEL_STATE_SMALL); } mCanceled = false; - mSelectorPaint.setAlpha(255); - invalidate(); } @Override @@ -588,20 +649,28 @@ public class NumberPicker extends LinearLayout { updateInputTextView(); updateIncrementAndDecrementButtonsVisibilityState(); - if (mFlingable && !isInEditMode()) { - // Start with shown selector wheel and hidden controls. When made - // visible hide the selector and fade-in the controls to suggest - // fling interaction. - setDrawScrollWheel(true); - hideInputControls(); + if (mFlingable) { + if (isInEditMode()) { + setSelectorWheelState(SELECTOR_WHEEL_STATE_SMALL); + } else { + // Start with shown selector wheel and hidden controls. When made + // visible hide the selector and fade-in the controls to suggest + // fling interaction. + setSelectorWheelState(SELECTOR_WHEEL_STATE_LARGE); + hideInputControls(); + } } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - // need to do this when we know our size - initializeScrollWheel(); + if (!mScrollWheelAndFadingEdgesInitialized) { + mScrollWheelAndFadingEdgesInitialized = true; + // need to do all this when we know our size + initializeSelectorWheel(); + initializeFadingEdges(); + } } @Override @@ -614,9 +683,10 @@ public class NumberPicker extends LinearLayout { mLastMotionEventY = mLastDownEventY = event.getY(); removeAllCallbacks(); mShowInputControlsAnimator.cancel(); + mDimSelectorWheelAnimator.cancel(); mBeginEditOnUpEvent = false; mAdjustScrollerOnUpEvent = true; - if (mDrawSelectorWheel) { + if (mSelectorWheelState == SELECTOR_WHEEL_STATE_LARGE) { boolean scrollersFinished = mFlingScroller.isFinished() && mAdjustScroller.isFinished(); if (!scrollersFinished) { @@ -635,7 +705,7 @@ public class NumberPicker extends LinearLayout { || (!mDecrementButton.isShown() && isEventInViewHitRect(event, mDecrementButton))) { mAdjustScrollerOnUpEvent = false; - setDrawScrollWheel(true); + setSelectorWheelState(SELECTOR_WHEEL_STATE_LARGE); hideInputControls(); return true; } @@ -646,7 +716,7 @@ public class NumberPicker extends LinearLayout { if (deltaDownY > mTouchSlop) { mBeginEditOnUpEvent = false; onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); - setDrawScrollWheel(true); + setSelectorWheelState(SELECTOR_WHEEL_STATE_LARGE); hideInputControls(); return true; } @@ -683,12 +753,9 @@ public class NumberPicker extends LinearLayout { break; case MotionEvent.ACTION_UP: if (mBeginEditOnUpEvent) { - setDrawScrollWheel(false); + setSelectorWheelState(SELECTOR_WHEEL_STATE_SMALL); showInputControls(mShowInputControlsAnimimationDuration); mInputText.requestFocus(); - InputMethodManager imm = (InputMethodManager) getContext().getSystemService( - Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(mInputText, 0); return true; } VelocityTracker velocityTracker = mVelocityTracker; @@ -715,10 +782,18 @@ public class NumberPicker extends LinearLayout { @Override public boolean dispatchTouchEvent(MotionEvent event) { - int action = event.getActionMasked(); - if ((action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) - && !isEventInViewHitRect(event, mInputText)) { - removeAllCallbacks(); + final int action = event.getActionMasked(); + switch (action) { + case MotionEvent.ACTION_MOVE: + if (mSelectorWheelState == SELECTOR_WHEEL_STATE_LARGE) { + removeAllCallbacks(); + forceCompleteChangeCurrentByOneViaScroll(); + } + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + removeAllCallbacks(); + break; } return super.dispatchTouchEvent(event); } @@ -743,7 +818,7 @@ public class NumberPicker extends LinearLayout { @Override public void computeScroll() { - if (!mDrawSelectorWheel) { + if (mSelectorWheelState == SELECTOR_WHEEL_STATE_NONE) { return; } Scroller scroller = mFlingScroller; @@ -777,7 +852,10 @@ public class NumberPicker extends LinearLayout { @Override public void scrollBy(int x, int y) { - int[] selectorIndices = getSelectorIndices(); + if (mSelectorWheelState == SELECTOR_WHEEL_STATE_NONE) { + return; + } + int[] selectorIndices = mSelectorIndices; if (!mWrapSelectorWheel && y > 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { mCurrentScrollOffset = mInitialScrollOffset; @@ -789,19 +867,19 @@ public class NumberPicker extends LinearLayout { return; } mCurrentScrollOffset += y; - while (mCurrentScrollOffset - mInitialScrollOffset >= mSelectorElementHeight) { + while (mCurrentScrollOffset - mInitialScrollOffset > mSelectorTextGapHeight) { mCurrentScrollOffset -= mSelectorElementHeight; decrementSelectorIndices(selectorIndices); changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); - if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { + if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { mCurrentScrollOffset = mInitialScrollOffset; } } - while (mCurrentScrollOffset - mInitialScrollOffset <= -mSelectorElementHeight) { + while (mCurrentScrollOffset - mInitialScrollOffset < -mSelectorTextGapHeight) { mCurrentScrollOffset += mSelectorElementHeight; - incrementScrollSelectorIndices(selectorIndices); + incrementSelectorIndices(selectorIndices); changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); - if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { + if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { mCurrentScrollOffset = mInitialScrollOffset; } } @@ -847,7 +925,7 @@ public class NumberPicker extends LinearLayout { return; } mFormatter = formatter; - resetSelectorWheelIndices(); + initializeSelectorWheelIndices(); updateInputTextView(); } @@ -890,8 +968,10 @@ public class NumberPicker extends LinearLayout { value = mWrapSelectorWheel ? mMinValue : mMaxValue; } mValue = value; + initializeSelectorWheelIndices(); updateInputTextView(); updateIncrementAndDecrementButtonsVisibilityState(); + invalidate(); } /** @@ -981,7 +1061,7 @@ public class NumberPicker extends LinearLayout { } boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; setWrapSelectorWheel(wrapSelectorWheel); - resetSelectorWheelIndices(); + initializeSelectorWheelIndices(); updateInputTextView(); } @@ -1012,7 +1092,7 @@ public class NumberPicker extends LinearLayout { } boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; setWrapSelectorWheel(wrapSelectorWheel); - resetSelectorWheelIndices(); + initializeSelectorWheelIndices(); updateInputTextView(); } @@ -1043,7 +1123,7 @@ public class NumberPicker extends LinearLayout { mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); } updateInputTextView(); - resetSelectorWheelIndices(); + initializeSelectorWheelIndices(); } @Override @@ -1080,18 +1160,19 @@ public class NumberPicker extends LinearLayout { @Override public void draw(Canvas canvas) { // Dispatch draw to our children only if we are not currently running - // the animation for simultaneously fading out the scroll wheel and + // the animation for simultaneously dimming the scroll wheel and // showing in the buttons. This class takes advantage of the View // implementation of fading edges effect to draw the selector wheel. // However, in View.draw(), the fading is applied after all the children // have been drawn and we do not want this fading to be applied to the - // buttons which are currently showing in. Therefore, we draw our - // children after we have completed drawing ourselves. + // buttons. Therefore, we draw our children after we have completed + // drawing ourselves. super.draw(canvas); // Draw our children if we are not showing the selector wheel of fading // it out - if (mShowInputControlsAnimator.isRunning() || !mDrawSelectorWheel) { + if (mShowInputControlsAnimator.isRunning() + || mSelectorWheelState != SELECTOR_WHEEL_STATE_LARGE) { long drawTime = getDrawingTime(); for (int i = 0, count = getChildCount(); i < count; i++) { View child = getChildAt(i); @@ -1105,25 +1186,32 @@ public class NumberPicker extends LinearLayout { @Override protected void onDraw(Canvas canvas) { - // we only draw the selector wheel - if (!mDrawSelectorWheel) { + if (mSelectorWheelState == SELECTOR_WHEEL_STATE_NONE) { return; } + float x = (mRight - mLeft) / 2; float y = mCurrentScrollOffset; + final int restoreCount = canvas.save(); + + if (mSelectorWheelState == SELECTOR_WHEEL_STATE_SMALL) { + Rect clipBounds = canvas.getClipBounds(); + clipBounds.inset(0, mSelectorElementHeight); + canvas.clipRect(clipBounds); + } + // draw the selector wheel - int[] selectorIndices = getSelectorIndices(); + int[] selectorIndices = mSelectorIndices; for (int i = 0; i < selectorIndices.length; i++) { int selectorIndex = selectorIndices[i]; String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex); - canvas.drawText(scrollSelectorValue, x, y, mSelectorPaint); + canvas.drawText(scrollSelectorValue, x, y, mSelectorWheelPaint); y += mSelectorElementHeight; } // draw the selection dividers (only if scrolling and drawable specified) if (mSelectionDivider != null) { - mSelectionDivider.setAlpha(mSelectorPaint.getAlpha()); // draw the top divider int topOfTopDivider = (getHeight() - mSelectorElementHeight - mSelectionDividerHeight) / 2; @@ -1137,6 +1225,8 @@ public class NumberPicker extends LinearLayout { mSelectionDivider.setBounds(0, topOfBottomDivider, mRight, bottomOfBottomDivider); mSelectionDivider.draw(canvas); } + + canvas.restoreToCount(restoreCount); } @Override @@ -1149,11 +1239,17 @@ public class NumberPicker extends LinearLayout { * Resets the selector indices and clear the cached * string representation of these indices. */ - private void resetSelectorWheelIndices() { + private void initializeSelectorWheelIndices() { mSelectorIndexToStringCache.clear(); - int[] selectorIdices = getSelectorIndices(); - for (int i = 0; i < selectorIdices.length; i++) { - selectorIdices[i] = Integer.MIN_VALUE; + int[] selectorIdices = mSelectorIndices; + int current = getValue(); + for (int i = 0; i < mSelectorIndices.length; i++) { + int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX); + if (mWrapSelectorWheel) { + selectorIndex = getWrappedSelectorIndex(selectorIndex); + } + mSelectorIndices[i] = selectorIndex; + ensureCachedScrollSelectorValue(mSelectorIndices[i]); } } @@ -1179,16 +1275,59 @@ public class NumberPicker extends LinearLayout { } /** + * Changes the current value by one which is increment or + * decrement based on the passes argument. + * + * @param increment True to increment, false to decrement. + */ + private void changeCurrentByOne(boolean increment) { + if (mFlingable) { + mDimSelectorWheelAnimator.cancel(); + mInputText.setVisibility(View.INVISIBLE); + mSelectorWheelPaint.setAlpha(SELECTOR_WHEEL_BRIGHT_ALPHA); + mPreviousScrollerY = 0; + forceCompleteChangeCurrentByOneViaScroll(); + if (increment) { + mFlingScroller.startScroll(0, 0, 0, -mSelectorElementHeight, + CHANGE_CURRENT_BY_ONE_SCROLL_DURATION); + } else { + mFlingScroller.startScroll(0, 0, 0, mSelectorElementHeight, + CHANGE_CURRENT_BY_ONE_SCROLL_DURATION); + } + invalidate(); + } else { + if (increment) { + changeCurrent(mValue + 1); + } else { + changeCurrent(mValue - 1); + } + } + } + + /** + * Ensures that if we are in the process of changing the current value + * by one via scrolling the scroller gets to its final state and the + * value is updated. + */ + private void forceCompleteChangeCurrentByOneViaScroll() { + Scroller scroller = mFlingScroller; + if (!scroller.isFinished()) { + final int yBeforeAbort = scroller.getCurrY(); + scroller.abortAnimation(); + final int yDelta = scroller.getCurrY() - yBeforeAbort; + scrollBy(0, yDelta); + } + } + + /** * Sets the <code>alpha</code> of the {@link Paint} for drawing the selector * wheel. */ @SuppressWarnings("unused") - // Called by ShowInputControlsAnimator via reflection + // Called via reflection private void setSelectorPaintAlpha(int alpha) { - mSelectorPaint.setAlpha(alpha); - if (mDrawSelectorWheel) { - invalidate(); - } + mSelectorWheelPaint.setAlpha(alpha); + invalidate(); } /** @@ -1200,14 +1339,15 @@ public class NumberPicker extends LinearLayout { } /** - * Sets if to <code>drawSelectionWheel</code>. + * Sets the <code>selectorWheelState</code>. */ - private void setDrawScrollWheel(boolean drawSelectorWheel) { - mDrawSelectorWheel = drawSelectorWheel; - // do not fade if the selector wheel not shown - setVerticalFadingEdgeEnabled(drawSelectorWheel); + private void setSelectorWheelState(int selectorWheelState) { + mSelectorWheelState = selectorWheelState; + if (selectorWheelState == SELECTOR_WHEEL_STATE_LARGE) { + mSelectorWheelPaint.setAlpha(SELECTOR_WHEEL_BRIGHT_ALPHA); + } - if (mFlingable && mDrawSelectorWheel + if (mFlingable && selectorWheelState == SELECTOR_WHEEL_STATE_LARGE && AccessibilityManager.getInstance(mContext).isEnabled()) { AccessibilityManager.getInstance(mContext).interrupt(); String text = mContext.getString(R.string.number_picker_increment_scroll_action); @@ -1217,16 +1357,14 @@ public class NumberPicker extends LinearLayout { } } - private void initializeScrollWheel() { - if (mInitialScrollOffset != Integer.MIN_VALUE) { - return; - } - int[] selectorIndices = getSelectorIndices(); + private void initializeSelectorWheel() { + initializeSelectorWheelIndices(); + int[] selectorIndices = mSelectorIndices; int totalTextHeight = selectorIndices.length * mTextSize; float totalTextGapHeight = (mBottom - mTop) - totalTextHeight; float textGapCount = selectorIndices.length - 1; - int selectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f); - mSelectorElementHeight = mTextSize + selectorTextGapHeight; + mSelectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f); + mSelectorElementHeight = mTextSize + mSelectorTextGapHeight; // Ensure that the middle item is positioned the same as the text in mInputText int editTextTextPosition = mInputText.getBaseline() + mInputText.getTop(); mInitialScrollOffset = editTextTextPosition - @@ -1235,13 +1373,23 @@ public class NumberPicker extends LinearLayout { updateInputTextView(); } + private void initializeFadingEdges() { + setVerticalFadingEdgeEnabled(true); + setFadingEdgeLength((mBottom - mTop - mTextSize) / 2); + } + /** * Callback invoked upon completion of a given <code>scroller</code>. */ private void onScrollerFinished(Scroller scroller) { if (scroller == mFlingScroller) { - postAdjustScrollerCommand(0); - onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); + if (mSelectorWheelState == SELECTOR_WHEEL_STATE_LARGE) { + postAdjustScrollerCommand(0); + onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); + } else { + updateInputTextView(); + fadeSelectorWheel(mShowInputControlsAnimimationDuration); + } } else { updateInputTextView(); showInputControls(mShowInputControlsAnimimationDuration); @@ -1312,6 +1460,17 @@ public class NumberPicker extends LinearLayout { } /** + * Fade the selector wheel via an animation. + * + * @param animationDuration The duration of the animation. + */ + private void fadeSelectorWheel(long animationDuration) { + mInputText.setVisibility(VISIBLE); + mDimSelectorWheelAnimator.setDuration(animationDuration); + mDimSelectorWheelAnimator.start(); + } + + /** * Updates the visibility state of the increment and decrement buttons. */ private void updateIncrementAndDecrementButtonsVisibilityState() { @@ -1328,25 +1487,6 @@ public class NumberPicker extends LinearLayout { } /** - * @return The selector indices array with proper values with the current as - * the middle one. - */ - private int[] getSelectorIndices() { - int current = getValue(); - if (mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] != current) { - for (int i = 0; i < mSelectorIndices.length; i++) { - int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX); - if (mWrapSelectorWheel) { - selectorIndex = getWrappedSelectorIndex(selectorIndex); - } - mSelectorIndices[i] = selectorIndex; - ensureCachedScrollSelectorValue(mSelectorIndices[i]); - } - } - return mSelectorIndices; - } - - /** * @return The wrapped index <code>selectorIndex</code> value. */ private int getWrappedSelectorIndex(int selectorIndex) { @@ -1362,7 +1502,7 @@ public class NumberPicker extends LinearLayout { * Increments the <code>selectorIndices</code> whose string representations * will be displayed in the selector. */ - private void incrementScrollSelectorIndices(int[] selectorIndices) { + private void incrementSelectorIndices(int[] selectorIndices) { for (int i = 0; i < selectorIndices.length - 1; i++) { selectorIndices[i] = selectorIndices[i + 1]; } @@ -1467,25 +1607,26 @@ public class NumberPicker extends LinearLayout { } /** - * Posts a command for updating the current value every <code>updateMillis - * </code>. + * Posts a command for changing the current value by one. + * + * @param increment Whether to increment or decrement the value. */ - private void postUpdateValueFromLongPress(int updateMillis) { + private void postChangeCurrentByOneFromLongPress(boolean increment) { mInputText.clearFocus(); removeAllCallbacks(); - if (mUpdateFromLongPressCommand == null) { - mUpdateFromLongPressCommand = new UpdateValueFromLongPressCommand(); + if (mChangeCurrentByOneFromLongPressCommand == null) { + mChangeCurrentByOneFromLongPressCommand = new ChangeCurrentByOneFromLongPressCommand(); } - mUpdateFromLongPressCommand.setUpdateStep(updateMillis); - post(mUpdateFromLongPressCommand); + mChangeCurrentByOneFromLongPressCommand.setIncrement(increment); + post(mChangeCurrentByOneFromLongPressCommand); } /** * Removes all pending callback from the message queue. */ private void removeAllCallbacks() { - if (mUpdateFromLongPressCommand != null) { - removeCallbacks(mUpdateFromLongPressCommand); + if (mChangeCurrentByOneFromLongPressCommand != null) { + removeCallbacks(mChangeCurrentByOneFromLongPressCommand); } if (mAdjustScrollerCommand != null) { removeCallbacks(mAdjustScrollerCommand); @@ -1658,17 +1799,17 @@ public class NumberPicker extends LinearLayout { } /** - * Command for updating the current value from a long press. + * Command for changing the current value from a long press by one. */ - class UpdateValueFromLongPressCommand implements Runnable { - private int mUpdateStep = 0; + class ChangeCurrentByOneFromLongPressCommand implements Runnable { + private boolean mIncrement; - private void setUpdateStep(int updateStep) { - mUpdateStep = updateStep; + private void setIncrement(boolean increment) { + mIncrement = increment; } public void run() { - changeCurrent(mValue + mUpdateStep); + changeCurrentByOne(mIncrement); postDelayed(this, mLongPressUpdateInterval); } } diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java index 17512d8c93d2..6a6d76766113 100644 --- a/core/java/android/widget/PopupMenu.java +++ b/core/java/android/widget/PopupMenu.java @@ -157,6 +157,8 @@ public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback { * @hide */ public boolean onOpenSubMenu(MenuBuilder subMenu) { + if (subMenu == null) return false; + if (!subMenu.hasVisibleItems()) { return true; } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index aac20c4434ad..8ba7beed3ffd 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -92,6 +92,7 @@ public class PopupWindow { private boolean mClipToScreen; private boolean mAllowScrollingAnchorParent = true; private boolean mLayoutInsetDecor = false; + private boolean mNotTouchModal; private OnTouchListener mTouchInterceptor; @@ -694,6 +695,15 @@ public class PopupWindow { } /** + * Set whether this window is touch modal or if outside touches will be sent to + * other windows behind it. + * @hide + */ + public void setTouchModal(boolean touchModal) { + mNotTouchModal = !touchModal; + } + + /** * <p>Change the width and height measure specs that are given to the * window manager by the popup. By default these are 0, meaning that * the current width or height is requested as an explicit size from @@ -1048,6 +1058,9 @@ public class PopupWindow { if (mLayoutInsetDecor) { curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; } + if (mNotTouchModal) { + curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; + } return curFlags; } diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index e033d2d0558f..df88fecc0618 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -937,7 +937,8 @@ public class ProgressBar extends View { int left = 0; if (mIndeterminateDrawable != null) { - if (mOnlyIndeterminate) { + // Aspect ratio logic does not apply to AnimationDrawables + if (mOnlyIndeterminate && !(mIndeterminateDrawable instanceof AnimationDrawable)) { // Maintain aspect ratio. Certain kinds of animated drawables // get very confused otherwise. final int intrinsicWidth = mIndeterminateDrawable.getIntrinsicWidth(); diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index d91eeb2d7d81..61ea5c9c211a 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -583,7 +583,7 @@ public class ScrollView extends FrameLayout { final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0); - if (canOverscroll && overScrollBy(0, deltaY, 0, mScrollY, + if (overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true)) { // Break our velocity if we hit a scroll barrier. mVelocityTracker.clear(); @@ -616,16 +616,12 @@ public class ScrollView extends FrameLayout { velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId); - final int bottom = getScrollRange(); - final int overscrollMode = getOverScrollMode(); - final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || - (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && bottom > 0); - - if (getChildCount() > 0 && canOverscroll) { + if (getChildCount() > 0) { if ((Math.abs(initialVelocity) > mMinimumVelocity)) { fling(-initialVelocity); } else { - if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, bottom)) { + if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, + getScrollRange())) { invalidate(); } } diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index f230031908cf..adf2b7b7a3f9 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -120,6 +120,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { private CharSequence mOldQueryText; private CharSequence mUserQuery; private boolean mExpandedInActionView; + private int mCollapsedImeOptions; private SearchableInfo mSearchable; private Bundle mAppSearchData; @@ -1166,6 +1167,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { clearFocus(); updateViewsVisibility(true); mQueryTextView.setText(""); + mQueryTextView.setImeOptions(mCollapsedImeOptions); mExpandedInActionView = false; } @@ -1175,6 +1177,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { @Override public void onActionViewExpanded() { mExpandedInActionView = true; + mCollapsedImeOptions = mQueryTextView.getImeOptions(); + mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN); setIconified(false); } diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java index 6e29024bcef4..36278907cea2 100644 --- a/core/java/android/widget/ShareActionProvider.java +++ b/core/java/android/widget/ShareActionProvider.java @@ -169,6 +169,7 @@ public class ShareActionProvider extends ActionProvider { mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true); Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId); activityChooserView.setExpandActivityOverflowButtonDrawable(drawable); + activityChooserView.setProvider(this); return activityChooserView; } diff --git a/core/java/android/widget/Space.java b/core/java/android/widget/Space.java index d7b2ec27fee4..bb53a7732f10 100644 --- a/core/java/android/widget/Space.java +++ b/core/java/android/widget/Space.java @@ -32,20 +32,24 @@ public final class Space extends View { */ public Space(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + if (getVisibility() == VISIBLE) { + setVisibility(INVISIBLE); + } } /** * {@inheritDoc} */ public Space(Context context, AttributeSet attrs) { - super(context, attrs); + this(context, attrs, 0); } /** * {@inheritDoc} */ public Space(Context context) { - super(context); + //noinspection NullableProblems + this(context, null); } /** @@ -58,22 +62,6 @@ public final class Space extends View { } /** - * {@inheritDoc} - */ - @Override - public ViewGroup.LayoutParams getLayoutParams() { - return super.getLayoutParams(); - } - - /** - * {@inheritDoc} - */ - @Override - public void setLayoutParams(ViewGroup.LayoutParams params) { - super.setLayoutParams(params); - } - - /** * Compare to: {@link View#getDefaultSize(int, int)} * If mode is AT_MOST, return the child size instead of the parent size * (unless it is too big). diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index 6b2f3e4faa19..ac9535a425d8 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -22,7 +22,6 @@ import android.text.Selection; import android.text.Spanned; import android.text.style.SpellCheckSpan; import android.text.style.SuggestionSpan; -import android.util.Log; import android.view.textservice.SpellCheckerSession; import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener; import android.view.textservice.SuggestionsInfo; @@ -40,23 +39,21 @@ import java.util.Locale; * @hide */ public class SpellChecker implements SpellCheckerSessionListener { - private static final String LOG_TAG = "SpellChecker"; - private static final boolean DEBUG_SPELL_CHECK = false; - private static final int DELAY_BEFORE_SPELL_CHECK = 400; // milliseconds private final TextView mTextView; final SpellCheckerSession mSpellCheckerSession; final int mCookie; - // Paired arrays for the (id, spellCheckSpan) pair. mIndex is the next available position + // Paired arrays for the (id, spellCheckSpan) pair. A negative id means the associated + // SpellCheckSpan has been recycled and can be-reused. + // May contain null SpellCheckSpans after a given index. private int[] mIds; private SpellCheckSpan[] mSpellCheckSpans; - // The actual current number of used slots in the above arrays + // The mLength first elements of the above arrays have been initialized private int mLength; private int mSpanSequenceCounter = 0; - private Runnable mChecker; public SpellChecker(TextView textView) { mTextView = textView; @@ -64,12 +61,14 @@ public class SpellChecker implements SpellCheckerSessionListener { final TextServicesManager textServicesManager = (TextServicesManager) textView.getContext(). getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); mSpellCheckerSession = textServicesManager.newSpellCheckerSession( - null /* not currently used by the textServicesManager */, Locale.getDefault(), + null /* not currently used by the textServicesManager */, + null /* null locale means use the languages defined in Settings + if referToSpellCheckerLanguageSettings is true */, this, true /* means use the languages defined in Settings */); mCookie = hashCode(); // Arbitrary: 4 simultaneous spell check spans. Will automatically double size on demand - final int size = ArrayUtils.idealObjectArraySize(4); + final int size = ArrayUtils.idealObjectArraySize(1); mIds = new int[size]; mSpellCheckSpans = new SpellCheckSpan[size]; mLength = 0; @@ -89,73 +88,50 @@ public class SpellChecker implements SpellCheckerSessionListener { } } - public void addSpellCheckSpan(SpellCheckSpan spellCheckSpan) { - int length = mIds.length; - if (mLength >= length) { - final int newSize = length * 2; + private int nextSpellCheckSpanIndex() { + for (int i = 0; i < mLength; i++) { + if (mIds[i] < 0) return i; + } + + if (mLength == mSpellCheckSpans.length) { + final int newSize = mLength * 2; int[] newIds = new int[newSize]; SpellCheckSpan[] newSpellCheckSpans = new SpellCheckSpan[newSize]; - System.arraycopy(mIds, 0, newIds, 0, length); - System.arraycopy(mSpellCheckSpans, 0, newSpellCheckSpans, 0, length); + System.arraycopy(mIds, 0, newIds, 0, mLength); + System.arraycopy(mSpellCheckSpans, 0, newSpellCheckSpans, 0, mLength); mIds = newIds; mSpellCheckSpans = newSpellCheckSpans; } - mIds[mLength] = mSpanSequenceCounter++; - mSpellCheckSpans[mLength] = spellCheckSpan; + mSpellCheckSpans[mLength] = new SpellCheckSpan(); mLength++; + return mLength - 1; + } - if (DEBUG_SPELL_CHECK) { - final Editable mText = (Editable) mTextView.getText(); - int start = mText.getSpanStart(spellCheckSpan); - int end = mText.getSpanEnd(spellCheckSpan); - if (start >= 0 && end >= 0) { - Log.d(LOG_TAG, "Schedule check " + mText.subSequence(start, end)); - } else { - Log.d(LOG_TAG, "Schedule check EMPTY!"); - } - } - - scheduleSpellCheck(); + public void addSpellCheckSpan(int wordStart, int wordEnd) { + final int index = nextSpellCheckSpanIndex(); + ((Editable) mTextView.getText()).setSpan(mSpellCheckSpans[index], wordStart, wordEnd, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + mIds[index] = mSpanSequenceCounter++; } public void removeSpellCheckSpan(SpellCheckSpan spellCheckSpan) { for (int i = 0; i < mLength; i++) { if (mSpellCheckSpans[i] == spellCheckSpan) { - removeAtIndex(i); + mSpellCheckSpans[i].setSpellCheckInProgress(false); + mIds[i] = -1; return; } } } - private void removeAtIndex(int i) { - System.arraycopy(mIds, i + 1, mIds, i, mLength - i - 1); - System.arraycopy(mSpellCheckSpans, i + 1, mSpellCheckSpans, i, mLength - i - 1); - mLength--; - } - public void onSelectionChanged() { - scheduleSpellCheck(); + spellCheck(); } - private void scheduleSpellCheck() { - if (mLength == 0) return; + public void spellCheck() { if (mSpellCheckerSession == null) return; - if (mChecker != null) { - mTextView.removeCallbacks(mChecker); - } - if (mChecker == null) { - mChecker = new Runnable() { - public void run() { - spellCheck(); - } - }; - } - mTextView.postDelayed(mChecker, DELAY_BEFORE_SPELL_CHECK); - } - - private void spellCheck() { final Editable editable = (Editable) mTextView.getText(); final int selectionStart = Selection.getSelectionStart(editable); final int selectionEnd = Selection.getSelectionEnd(editable); @@ -164,8 +140,7 @@ public class SpellChecker implements SpellCheckerSessionListener { int textInfosCount = 0; for (int i = 0; i < mLength; i++) { - SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i]; - + final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i]; if (spellCheckSpan.isSpellCheckInProgress()) continue; final int start = editable.getSpanStart(spellCheckSpan); @@ -174,7 +149,7 @@ public class SpellChecker implements SpellCheckerSessionListener { // Do not check this word if the user is currently editing it if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) { final String word = editable.subSequence(start, end).toString(); - spellCheckSpan.setSpellCheckInProgress(); + spellCheckSpan.setSpellCheckInProgress(true); textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]); } } @@ -196,48 +171,30 @@ public class SpellChecker implements SpellCheckerSessionListener { for (int i = 0; i < results.length; i++) { SuggestionsInfo suggestionsInfo = results[i]; if (suggestionsInfo.getCookie() != mCookie) continue; - final int sequenceNumber = suggestionsInfo.getSequence(); - // Starting from the end, to limit the number of array copy while removing - for (int j = mLength - 1; j >= 0; j--) { + + for (int j = 0; j < mLength; j++) { + final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j]; + if (sequenceNumber == mIds[j]) { - SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j]; final int attributes = suggestionsInfo.getSuggestionsAttributes(); boolean isInDictionary = ((attributes & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) > 0); boolean looksLikeTypo = ((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0); - if (DEBUG_SPELL_CHECK) { - final int start = editable.getSpanStart(spellCheckSpan); - final int end = editable.getSpanEnd(spellCheckSpan); - Log.d(LOG_TAG, "Result sequence=" + suggestionsInfo.getSequence() + " " + - editable.subSequence(start, end) + - "\t" + (isInDictionary?"IN_DICT" : "NOT_DICT") + - "\t" + (looksLikeTypo?"TYPO" : "NOT_TYPO")); - } - if (!isInDictionary && looksLikeTypo) { String[] suggestions = getSuggestions(suggestionsInfo); - if (suggestions.length > 0) { - SuggestionSpan suggestionSpan = new SuggestionSpan( - mTextView.getContext(), suggestions, - SuggestionSpan.FLAG_EASY_CORRECT | - SuggestionSpan.FLAG_MISSPELLED); - final int start = editable.getSpanStart(spellCheckSpan); - final int end = editable.getSpanEnd(spellCheckSpan); - editable.setSpan(suggestionSpan, start, end, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - // TODO limit to the word rectangle region - mTextView.invalidate(); - - if (DEBUG_SPELL_CHECK) { - String suggestionsString = ""; - for (String s : suggestions) { suggestionsString += s + "|"; } - Log.d(LOG_TAG, " Suggestions for " + sequenceNumber + " " + - editable.subSequence(start, end)+ " " + suggestionsString); - } - } + SuggestionSpan suggestionSpan = new SuggestionSpan( + mTextView.getContext(), suggestions, + SuggestionSpan.FLAG_EASY_CORRECT | + SuggestionSpan.FLAG_MISSPELLED); + final int start = editable.getSpanStart(spellCheckSpan); + final int end = editable.getSpanEnd(spellCheckSpan); + editable.setSpan(suggestionSpan, start, end, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + // TODO limit to the word rectangle region + mTextView.invalidate(); } editable.removeSpan(spellCheckSpan); } @@ -246,9 +203,10 @@ public class SpellChecker implements SpellCheckerSessionListener { } private static String[] getSuggestions(SuggestionsInfo suggestionsInfo) { + // A negative suggestion count is possible final int len = Math.max(0, suggestionsInfo.getSuggestionsCount()); String[] suggestions = new String[len]; - for (int j = 0; j < len; ++j) { + for (int j = 0; j < len; j++) { suggestions[j] = suggestionsInfo.getSuggestionAt(j); } return suggestions; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 204c94a0599f..5cd79024f7ad 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -3250,7 +3250,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sendOnTextChanged(text, 0, oldlen, textLength); onTextChanged(text, 0, oldlen, textLength); - if (startSpellCheck && getSpellChecker().isSessionActive()) { + if (startSpellCheck && mSpellChecker != null) { + // This view has to have been previously attached for mSpellChecker to exist updateSpellCheckSpans(0, textLength); } @@ -4412,6 +4413,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Resolve drawables as the layout direction has been resolved resolveDrawables(); + + updateSpellCheckSpans(0, mText.length()); } @Override @@ -4443,6 +4446,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener hideControllers(); resetResolvedDrawables(); + + if (mSpellChecker != null) { + mSpellChecker.closeSession(); + removeMisspelledSpans(); + // Forces the creation of a new SpellChecker next time this window is created. + // Will handle the cases where the settings has been changed in the meantime. + mSpellChecker = null; + } } @Override @@ -5526,7 +5537,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public boolean onCheckIsTextEditor() { return mInputType != EditorInfo.TYPE_NULL; } - + @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { if (onCheckIsTextEditor() && isEnabled()) { if (mInputMethodState == null) { @@ -6130,7 +6141,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener TruncateAt effectiveEllipsize = mEllipsize; if (mEllipsize == TruncateAt.MARQUEE && mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) { - effectiveEllipsize = TruncateAt.END; + effectiveEllipsize = TruncateAt.END_SMALL; } if (mTextDir == null) { @@ -6242,7 +6253,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener result = new DynamicLayout(mText, mTransformed, mTextPaint, w, alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad, mInput == null ? effectiveEllipsize : null, - ellipsisWidth); + ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE); } else { if (boring == UNKNOWN_BORING) { boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring); @@ -7481,9 +7492,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ protected void onSelectionChanged(int selStart, int selEnd) { sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); - if (mSpellChecker != null) { - mSpellChecker.onSelectionChanged(); - } } /** @@ -7542,6 +7550,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener for (int i = 0; i < length; i++) { final int s = text.getSpanStart(spans[i]); final int e = text.getSpanEnd(spans[i]); + // Spans that are adjacent to the edited region will be handled in + // updateSpellCheckSpans. Result depends on what will be added (space or text) if (e == start || s == end) break; text.removeSpan(spans[i]); } @@ -7599,12 +7609,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sendOnTextChanged(buffer, start, before, after); onTextChanged(buffer, start, before, after); - if (getSpellChecker().isSessionActive()) { - // The WordIterator text change listener may be called after this one. - // Make sure this changed text is rescanned before the iterator is used on it. - getWordIterator().forceUpdate(); - updateSpellCheckSpans(start, start + after); - } + updateSpellCheckSpans(start, start + after); // Hide the controllers if the amount of content changed if (before != after) { @@ -7726,12 +7731,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - if (what instanceof SpellCheckSpan) { - if (newStart < 0) { - getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what); - } else if (oldStart < 0) { - getSpellChecker().addSpellCheckSpan((SpellCheckSpan) what); - } + if (newStart < 0 && what instanceof SpellCheckSpan) { + getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what); } } @@ -7739,78 +7740,98 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Create new SpellCheckSpans on the modified region. */ private void updateSpellCheckSpans(int start, int end) { - if (!(mText instanceof Editable) || !isSuggestionsEnabled()) return; + if (!isTextEditable() || !isSuggestionsEnabled() || !getSpellChecker().isSessionActive()) + return; Editable text = (Editable) mText; - WordIterator wordIterator = getWordIterator(); - wordIterator.setCharSequence(text); + final int shift = prepareWordIterator(start, end); + final int shiftedStart = start - shift; + final int shiftedEnd = end - shift; // Move back to the beginning of the current word, if any - int wordStart = wordIterator.preceding(start); + int wordStart = mWordIterator.preceding(shiftedStart); int wordEnd; if (wordStart == BreakIterator.DONE) { - wordEnd = wordIterator.following(start); + wordEnd = mWordIterator.following(shiftedStart); if (wordEnd != BreakIterator.DONE) { - wordStart = wordIterator.getBeginning(wordEnd); + wordStart = mWordIterator.getBeginning(wordEnd); } } else { - wordEnd = wordIterator.getEnd(wordStart); + wordEnd = mWordIterator.getEnd(wordStart); } if (wordEnd == BreakIterator.DONE) { return; } + // We need to expand by one character because we want to include the spans that end/start + // at position start/end respectively. + SpellCheckSpan[] spellCheckSpans = text.getSpans(start - 1, end + 1, SpellCheckSpan.class); + SuggestionSpan[] suggestionSpans = text.getSpans(start - 1, end + 1, SuggestionSpan.class); + final int numberOfSpellCheckSpans = spellCheckSpans.length; + // Iterate over the newly added text and schedule new SpellCheckSpans - while (wordStart <= end) { - if (wordEnd >= start) { - // A word across the interval boundaries must remove boundary edition spans - if (wordStart < start && wordEnd > start) { - removeEditionSpansAt(start, text); + while (wordStart <= shiftedEnd) { + if (wordEnd >= shiftedStart) { + // A new word has been created across the interval boundaries. Remove previous spans + if (wordStart < shiftedStart && wordEnd > shiftedStart) { + removeSpansAt(start, spellCheckSpans, text); + removeSpansAt(start, suggestionSpans, text); } - if (wordStart < end && wordEnd > end) { - removeEditionSpansAt(end, text); + if (wordStart < shiftedEnd && wordEnd > shiftedEnd) { + removeSpansAt(end, spellCheckSpans, text); + removeSpansAt(end, suggestionSpans, text); } // Do not create new boundary spans if they already exist boolean createSpellCheckSpan = true; - if (wordEnd == start) { - SpellCheckSpan[] spellCheckSpans = text.getSpans(start, start, - SpellCheckSpan.class); - if (spellCheckSpans.length > 0) createSpellCheckSpan = false; + if (wordEnd == shiftedStart) { + for (int i = 0; i < numberOfSpellCheckSpans; i++) { + final int spanEnd = text.getSpanEnd(spellCheckSpans[i]); + if (spanEnd == start) { + createSpellCheckSpan = false; + break; + } + } } - if (wordStart == end) { - SpellCheckSpan[] spellCheckSpans = text.getSpans(end, end, - SpellCheckSpan.class); - if (spellCheckSpans.length > 0) createSpellCheckSpan = false; + if (wordStart == shiftedEnd) { + for (int i = 0; i < numberOfSpellCheckSpans; i++) { + final int spanStart = text.getSpanStart(spellCheckSpans[i]); + if (spanStart == end) { + createSpellCheckSpan = false; + break; + } + } } if (createSpellCheckSpan) { - text.setSpan(new SpellCheckSpan(), wordStart, wordEnd, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + mSpellChecker.addSpellCheckSpan(wordStart + shift, wordEnd + shift); } } // iterate word by word - wordEnd = wordIterator.following(wordEnd); - if (wordEnd == BreakIterator.DONE) return; - wordStart = wordIterator.getBeginning(wordEnd); + wordEnd = mWordIterator.following(wordEnd); + if (wordEnd == BreakIterator.DONE) break; + wordStart = mWordIterator.getBeginning(wordEnd); if (wordStart == BreakIterator.DONE) { - Log.e(LOG_TAG, "Unable to find word beginning from " + wordEnd + "in " + mText); - return; + Log.e(LOG_TAG, "No word beginning from " + (wordEnd + shift) + "in " + mText); + break; } } + + mSpellChecker.spellCheck(); } - private static void removeEditionSpansAt(int offset, Editable text) { - SuggestionSpan[] suggestionSpans = text.getSpans(offset, offset, SuggestionSpan.class); - for (int i = 0; i < suggestionSpans.length; i++) { - text.removeSpan(suggestionSpans[i]); - } - SpellCheckSpan[] spellCheckSpans = text.getSpans(offset, offset, SpellCheckSpan.class); - for (int i = 0; i < spellCheckSpans.length; i++) { - text.removeSpan(spellCheckSpans[i]); + private static <T> void removeSpansAt(int offset, T[] spans, Editable text) { + final int length = spans.length; + for (int i = 0; i < length; i++) { + final T span = spans[i]; + final int start = text.getSpanStart(span); + if (start > offset) continue; + final int end = text.getSpanEnd(span); + if (end < offset) continue; + text.removeSpan(span); } } @@ -8256,10 +8277,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mBlink.uncancel(); makeBlink(); } - if (getSpellChecker().isSessionActive() && (mSuggestionsPopupWindow == null || - !mSuggestionsPopupWindow.mSuggestionPopupWindowVisible)) { - updateSpellCheckSpans(0, mText.length()); - } } else { if (mBlink != null) { mBlink.cancel(); @@ -8271,16 +8288,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } hideControllers(); - - if (mSpellChecker != null && (mSuggestionsPopupWindow == null || - !mSuggestionsPopupWindow.mSuggestionPopupWindowVisible)) { - mSpellChecker.closeSession(); - removeMisspelledSpans(); - // Forces the creation of a new SpellChecker next time this window if focused. - // Will handle the cases where the service has been enabled or disabled in - // settings in the meantime. - mSpellChecker = null; - } } startStopMarquee(hasWindowFocus); @@ -8385,6 +8392,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect(); hideControllers(); if (!selectAllGotFocus && mText.length() > 0) { + if (mSpellChecker != null) { + // When the cursor moves, the word that was typed may need spell check + mSpellChecker.onSelectionChanged(); + } if (isCursorInsideEasyCorrectionSpan()) { showSuggestions(); } else if (hasInsertionController()) { @@ -8928,26 +8939,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener selectionStart = ((Spanned) mText).getSpanStart(url); selectionEnd = ((Spanned) mText).getSpanEnd(url); } else { - WordIterator wordIterator = getWordIterator(); - // WordIterator handles text changes, this is a no-op if text in unchanged. - wordIterator.setCharSequence(mText); + final int shift = prepareWordIterator(minOffset, maxOffset); - selectionStart = wordIterator.getBeginning(minOffset); + selectionStart = mWordIterator.getBeginning(minOffset - shift); if (selectionStart == BreakIterator.DONE) return false; + selectionStart += shift; - selectionEnd = wordIterator.getEnd(maxOffset); + selectionEnd = mWordIterator.getEnd(maxOffset - shift); if (selectionEnd == BreakIterator.DONE) return false; + selectionEnd += shift; } Selection.setSelection((Spannable) mText, selectionStart, selectionEnd); return true; } - WordIterator getWordIterator() { + int prepareWordIterator(int start, int end) { if (mWordIterator == null) { mWordIterator = new WordIterator(); } - return mWordIterator; + + final int TEXT_WINDOW_WIDTH = 50; // Should be larger than the longest word's length + final int windowStart = Math.max(0, start - TEXT_WINDOW_WIDTH); + final int windowEnd = Math.min(mText.length(), end + TEXT_WINDOW_WIDTH); + mWordIterator.setCharSequence(mText.subSequence(windowStart, windowEnd)); + + return windowStart; } private SpellChecker getSpellChecker() { @@ -9175,19 +9192,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return true; case ID_CUT: - setPrimaryClip(ClipData.newPlainText(null, mTransformed.subSequence(min, max))); + setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max))); ((Editable) mText).delete(min, max); stopSelectionActionMode(); return true; case ID_COPY: - setPrimaryClip(ClipData.newPlainText(null, mTransformed.subSequence(min, max))); + setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max))); stopSelectionActionMode(); return true; } return false; } + private CharSequence getTransformedText(int start, int end) { + return removeSuggestionSpans(mTransformed.subSequence(start, end)); + } + /** * Prepare text so that there are not zero or two spaces at beginning and end of region defined * by [min, max] when replacing this region by paste. @@ -9304,7 +9325,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Start a drag final int start = getSelectionStart(); final int end = getSelectionEnd(); - CharSequence selectedText = mTransformed.subSequence(start, end); + CharSequence selectedText = getTransformedText(start, end); ClipData data = ClipData.newPlainText(null, selectedText); DragLocalState localState = new DragLocalState(this, start, end); startDrag(data, getTextThumbnailBuilder(selectedText), localState, 0); @@ -9467,8 +9488,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } - int posX = mPositionX + positionX; - int posY = mPositionY + positionY; + int posX = mPositionX + positionX - getScrollX(); + int posY = mPositionY + positionY - getScrollY(); // Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal. return posX >= clip.left - 1 && posX <= clip.right + 1 && @@ -9600,10 +9621,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener { private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE; + private static final int ADD_TO_DICTIONARY = -1; + private static final int DELETE_TEXT = -2; private SuggestionInfo[] mSuggestionInfos; private int mNumberOfSuggestions; private boolean mCursorWasVisibleBeforeSuggestions; - private boolean mSuggestionPopupWindowVisible; private SuggestionAdapter mSuggestionsAdapter; private final Comparator<SuggestionSpan> mSuggestionSpanComparator; private final HashMap<SuggestionSpan, Integer> mSpansLengths; @@ -9615,7 +9637,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void dismiss() { - mSuggestionPopupWindowVisible = false; super.dismiss(); TextView.this.getPositionListener().removeSubscriber(SuggestionsPopupWindow.this); @@ -9653,9 +9674,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener listView.setOnItemClickListener(this); mContentView = listView; - // Inflate the suggestion items once and for all. +1 for add to dictionary - mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 1]; - for (int i = 0; i < MAX_NUMBER_SUGGESTIONS + 1; i++) { + // Inflate the suggestion items once and for all. + 2 for add to dictionary and delete + mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 2]; + for (int i = 0; i < mSuggestionInfos.length; i++) { mSuggestionInfos[i] = new SuggestionInfo(); } } @@ -9706,7 +9727,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener false); } - textView.setText(mSuggestionInfos[position].text); + final SuggestionInfo suggestionInfo = mSuggestionInfos[position]; + textView.setText(suggestionInfo.text); + + if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) { + textView.setCompoundDrawablesWithIntrinsicBounds( + com.android.internal.R.drawable.ic_suggestions_add, 0, 0, 0); + } else if (suggestionInfo.suggestionIndex == DELETE_TEXT) { + textView.setCompoundDrawablesWithIntrinsicBounds( + com.android.internal.R.drawable.ic_suggestions_delete, 0, 0, 0); + } else { + textView.setCompoundDrawables(null, null, null, null); + } + return textView; } } @@ -9757,12 +9790,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void show() { if (!(mText instanceof Editable)) return; - if (updateSuggestions()) { - mCursorWasVisibleBeforeSuggestions = mCursorVisible; - mSuggestionPopupWindowVisible = true; - setCursorVisible(false); - super.show(); - } + updateSuggestions(); + mCursorWasVisibleBeforeSuggestions = mCursorVisible; + setCursorVisible(false); + super.show(); } @Override @@ -9777,6 +9808,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener View view = null; for (int i = 0; i < mNumberOfSuggestions; i++) { view = mSuggestionsAdapter.getView(i, view, mContentView); + view.getLayoutParams().width = LayoutParams.WRAP_CONTENT; view.measure(horizontalMeasure, verticalMeasure); width = Math.max(width, view.getMeasuredWidth()); } @@ -9817,7 +9849,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener super.hide(); } - private boolean updateSuggestions() { + private void updateSuggestions() { Spannable spannable = (Spannable) TextView.this.mText; SuggestionSpan[] suggestionSpans = getSuggestionSpans(); @@ -9866,21 +9898,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd); } + // Add to dictionary item is there a span with the misspelled flag if (misspelledSpan != null) { final int misspelledStart = spannable.getSpanStart(misspelledSpan); final int misspelledEnd = spannable.getSpanEnd(misspelledSpan); if (misspelledStart >= 0 && misspelledEnd > misspelledStart) { SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions]; suggestionInfo.suggestionSpan = misspelledSpan; - suggestionInfo.suggestionIndex = -1; + suggestionInfo.suggestionIndex = ADD_TO_DICTIONARY; suggestionInfo.text.replace(0, suggestionInfo.text.length(), getContext().getString(com.android.internal.R.string.addToDictionary)); + suggestionInfo.text.setSpan(suggestionInfo.highlightSpan, 0, 0, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mNumberOfSuggestions++; } } - if (mNumberOfSuggestions == 0) return false; + // Delete item + SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions]; + suggestionInfo.suggestionSpan = null; + suggestionInfo.suggestionIndex = DELETE_TEXT; + suggestionInfo.text.replace(0, suggestionInfo.text.length(), + getContext().getString(com.android.internal.R.string.deleteText)); + suggestionInfo.text.setSpan(suggestionInfo.highlightSpan, 0, 0, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + mNumberOfSuggestions++; if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan(); if (underlineColor == 0) { @@ -9896,8 +9939,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mSuggestionsAdapter.notifyDataSetChanged(); - - return true; } private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart, @@ -9910,8 +9951,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener suggestionInfo.suggestionStart = spanStart - unionStart; suggestionInfo.suggestionEnd = suggestionInfo.suggestionStart + suggestionInfo.text.length(); - - suggestionInfo.text.clearSpans(); + suggestionInfo.text.setSpan(suggestionInfo.highlightSpan, 0, suggestionInfo.text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -9922,74 +9962,93 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - if (view instanceof TextView) { - TextView textView = (TextView) view; - Editable editable = (Editable) mText; - - SuggestionInfo suggestionInfo = mSuggestionInfos[position]; - final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan); - final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan); - final String originalText = mText.subSequence(spanStart, spanEnd).toString(); - - if (suggestionInfo.suggestionIndex < 0) { - Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT); - intent.putExtra("word", originalText); - intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); - getContext().startActivity(intent); - suggestionInfo.removeMisspelledFlag(); - } else { - // SuggestionSpans are removed by replace: save them before - SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd, - SuggestionSpan.class); - final int length = suggestionSpans.length; - int[] suggestionSpansStarts = new int[length]; - int[] suggestionSpansEnds = new int[length]; - int[] suggestionSpansFlags = new int[length]; - for (int i = 0; i < length; i++) { - final SuggestionSpan suggestionSpan = suggestionSpans[i]; - suggestionSpansStarts[i] = editable.getSpanStart(suggestionSpan); - suggestionSpansEnds[i] = editable.getSpanEnd(suggestionSpan); - suggestionSpansFlags[i] = editable.getSpanFlags(suggestionSpan); - } + TextView textView = (TextView) view; + Editable editable = (Editable) mText; - final int suggestionStart = suggestionInfo.suggestionStart; - final int suggestionEnd = suggestionInfo.suggestionEnd; - final String suggestion = textView.getText().subSequence( - suggestionStart, suggestionEnd).toString(); - editable.replace(spanStart, spanEnd, suggestion); + SuggestionInfo suggestionInfo = mSuggestionInfos[position]; - suggestionInfo.removeMisspelledFlag(); + if (suggestionInfo.suggestionIndex == DELETE_TEXT) { + final int spanUnionStart = editable.getSpanStart(mSuggestionRangeSpan); + int spanUnionEnd = editable.getSpanEnd(mSuggestionRangeSpan); + // Do not leave two adjacent spaces after deletion, or one at beginning of text + if (spanUnionEnd < editable.length() && + Character.isSpaceChar(editable.charAt(spanUnionEnd)) && + (spanUnionStart == 0 || + Character.isSpaceChar(editable.charAt(spanUnionStart - 1)))) { + spanUnionEnd = spanUnionEnd + 1; + } + editable.replace(spanUnionStart, spanUnionEnd, ""); + hide(); + return; + } - // Notify source IME of the suggestion pick. Do this before swaping texts. - if (!TextUtils.isEmpty( - suggestionInfo.suggestionSpan.getNotificationTargetClassName())) { - InputMethodManager imm = InputMethodManager.peekInstance(); - imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText, - suggestionInfo.suggestionIndex); - } + final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan); + final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan); + if (spanStart < 0 || spanEnd < 0) { + // Span has been removed + hide(); + return; + } + final String originalText = mText.subSequence(spanStart, spanEnd).toString(); - // Swap text content between actual text and Suggestion span - String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions(); - suggestions[suggestionInfo.suggestionIndex] = originalText; - - // Restore previous SuggestionSpans - final int lengthDifference = suggestion.length() - (spanEnd - spanStart); - for (int i = 0; i < length; i++) { - // Only spans that include the modified region make sense after replacement - // Spans partially included in the replaced region are removed, there is no - // way to assign them a valid range after replacement - if (suggestionSpansStarts[i] <= spanStart && - suggestionSpansEnds[i] >= spanEnd) { - editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i], - suggestionSpansEnds[i] + lengthDifference, - suggestionSpansFlags[i]); - } + if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) { + Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT); + intent.putExtra("word", originalText); + intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); + getContext().startActivity(intent); + suggestionInfo.removeMisspelledFlag(); + } else { + // SuggestionSpans are removed by replace: save them before + SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd, + SuggestionSpan.class); + final int length = suggestionSpans.length; + int[] suggestionSpansStarts = new int[length]; + int[] suggestionSpansEnds = new int[length]; + int[] suggestionSpansFlags = new int[length]; + for (int i = 0; i < length; i++) { + final SuggestionSpan suggestionSpan = suggestionSpans[i]; + suggestionSpansStarts[i] = editable.getSpanStart(suggestionSpan); + suggestionSpansEnds[i] = editable.getSpanEnd(suggestionSpan); + suggestionSpansFlags[i] = editable.getSpanFlags(suggestionSpan); + } + + final int suggestionStart = suggestionInfo.suggestionStart; + final int suggestionEnd = suggestionInfo.suggestionEnd; + final String suggestion = textView.getText().subSequence( + suggestionStart, suggestionEnd).toString(); + editable.replace(spanStart, spanEnd, suggestion); + + suggestionInfo.removeMisspelledFlag(); + + // Notify source IME of the suggestion pick. Do this before swaping texts. + if (!TextUtils.isEmpty( + suggestionInfo.suggestionSpan.getNotificationTargetClassName())) { + InputMethodManager imm = InputMethodManager.peekInstance(); + imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText, + suggestionInfo.suggestionIndex); + } + + // Swap text content between actual text and Suggestion span + String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions(); + suggestions[suggestionInfo.suggestionIndex] = originalText; + + // Restore previous SuggestionSpans + final int lengthDifference = suggestion.length() - (spanEnd - spanStart); + for (int i = 0; i < length; i++) { + // Only spans that include the modified region make sense after replacement + // Spans partially included in the replaced region are removed, there is no + // way to assign them a valid range after replacement + if (suggestionSpansStarts[i] <= spanStart && + suggestionSpansEnds[i] >= spanEnd) { + editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i], + suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]); } - - // Move cursor at the end of the replacement word - Selection.setSelection(editable, spanEnd + lengthDifference); } + + // Move cursor at the end of the replacement word + Selection.setSelection(editable, spanEnd + lengthDifference); } + hide(); } } diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index 88a0e0130473..8e438ffe4678 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -456,13 +456,6 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { seekTo(mSeekWhenPrepared); } start(); - if (mMediaController != null) { - if (mMediaController.isShowing()) { - // ensure the controller will get repositioned later - mMediaController.hide(); - } - mMediaController.show(); - } } } diff --git a/core/java/com/android/internal/policy/IFaceLockCallback.aidl b/core/java/com/android/internal/policy/IFaceLockCallback.aidl index 1eadc412810b..4f76c7131f48 100644 --- a/core/java/com/android/internal/policy/IFaceLockCallback.aidl +++ b/core/java/com/android/internal/policy/IFaceLockCallback.aidl @@ -21,5 +21,4 @@ import android.os.IBinder; oneway interface IFaceLockCallback { void unlock(); void cancel(); - void sleepDevice(); } diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 159929b19f7a..3d229295ca7a 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -133,4 +133,13 @@ public class ArrayUtils } return false; } + + public static boolean contains(int[] array, int value) { + for (int element : array) { + if (element == value) { + return true; + } + } + return false; + } } diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index fba6a5a3a049..aabea2c91458 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -24,6 +24,7 @@ import android.content.res.Resources; import android.os.Parcel; import android.os.Parcelable; import android.util.SparseBooleanArray; +import android.view.ActionProvider; import android.view.MenuItem; import android.view.SoundEffectConstants; import android.view.View; @@ -40,7 +41,8 @@ import java.util.ArrayList; /** * MenuPresenter for building action menus as seen in the action bar and action modes. */ -public class ActionMenuPresenter extends BaseMenuPresenter { +public class ActionMenuPresenter extends BaseMenuPresenter + implements ActionProvider.SubUiVisibilityListener { private static final String TAG = "ActionMenuPresenter"; private View mOverflowButton; @@ -187,8 +189,30 @@ public class ActionMenuPresenter extends BaseMenuPresenter { public void updateMenuView(boolean cleared) { super.updateMenuView(cleared); - final boolean hasOverflow = mReserveOverflow && mMenu != null && - mMenu.getNonActionItems().size() > 0; + if (mMenu != null) { + final ArrayList<MenuItemImpl> actionItems = mMenu.getActionItems(); + final int count = actionItems.size(); + for (int i = 0; i < count; i++) { + final ActionProvider provider = actionItems.get(i).getActionProvider(); + if (provider != null) { + provider.setSubUiVisibilityListener(this); + } + } + } + + final ArrayList<MenuItemImpl> nonActionItems = mMenu != null ? + mMenu.getNonActionItems() : null; + + boolean hasOverflow = false; + if (mReserveOverflow && nonActionItems != null) { + final int count = nonActionItems.size(); + if (count == 1) { + hasOverflow = !nonActionItems.get(0).isActionViewExpanded(); + } else { + hasOverflow = count > 0; + } + } + if (hasOverflow) { if (mOverflowButton == null) { mOverflowButton = new OverflowMenuButton(mContext); @@ -483,6 +507,16 @@ public class ActionMenuPresenter extends BaseMenuPresenter { } } + @Override + public void onSubUiVisibilityChanged(boolean isVisible) { + if (isVisible) { + // Not a submenu, but treat it like one. + super.onSubMenuSelected(null); + } else { + mMenu.close(false); + } + } + private static class SavedState implements Parcelable { public int openSubMenuId; @@ -590,7 +624,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter { @Override public void onDismiss() { super.onDismiss(); - mSubMenu.close(); mActionButtonPopup = null; mOpenSubMenuId = 0; } @@ -600,12 +633,17 @@ public class ActionMenuPresenter extends BaseMenuPresenter { @Override public boolean onOpenSubMenu(MenuBuilder subMenu) { + if (subMenu == null) return false; + mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId(); return false; } @Override public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + if (menu instanceof SubMenuBuilder) { + ((SubMenuBuilder) menu).getRootMenu().close(false); + } } } diff --git a/core/java/com/android/internal/view/menu/IconMenuPresenter.java b/core/java/com/android/internal/view/menu/IconMenuPresenter.java index d1b1dae80315..24ddad668ac3 100644 --- a/core/java/com/android/internal/view/menu/IconMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/IconMenuPresenter.java @@ -187,7 +187,9 @@ public class IconMenuPresenter extends BaseMenuPresenter { @Override public boolean onOpenSubMenu(MenuBuilder subMenu) { - mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId(); + if (subMenu != null) { + mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId(); + } return false; } diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java index 014142729dc1..a331bec53dc4 100644 --- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java @@ -17,6 +17,7 @@ package com.android.internal.view.menu; import android.content.Context; +import android.database.DataSetObserver; import android.os.Bundle; import android.os.Parcelable; import android.util.SparseArray; @@ -47,7 +48,7 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick int mItemLayoutRes; private Callback mCallback; - private MenuAdapter mAdapter; + MenuAdapter mAdapter; private int mId; @@ -216,14 +217,29 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick } private class MenuAdapter extends BaseAdapter { + private int mExpandedIndex = -1; + + public MenuAdapter() { + registerDataSetObserver(new ExpandedIndexObserver()); + findExpandedIndex(); + } + public int getCount() { ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); - return items.size() - mItemIndexOffset; + int count = items.size() - mItemIndexOffset; + if (mExpandedIndex < 0) { + return count; + } + return count - 1; } public MenuItemImpl getItem(int position) { ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); - return items.get(position + mItemIndexOffset); + position += mItemIndexOffset; + if (mExpandedIndex >= 0 && position >= mExpandedIndex) { + position++; + } + return items.get(position); } public long getItemId(int position) { @@ -241,5 +257,28 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick itemView.initialize(getItem(position), 0); return convertView; } + + void findExpandedIndex() { + final MenuItemImpl expandedItem = mMenu.getExpandedItem(); + if (expandedItem != null) { + final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); + final int count = items.size(); + for (int i = 0; i < count; i++) { + final MenuItemImpl item = items.get(i); + if (item == expandedItem) { + mExpandedIndex = i; + return; + } + } + } + mExpandedIndex = -1; + } + } + + private class ExpandedIndexObserver extends DataSetObserver { + @Override + public void onChanged() { + mAdapter.findExpandedIndex(); + } } } diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index c30e83b670ed..9fbca824f202 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -1258,4 +1258,8 @@ public class MenuBuilder implements Menu { } return collapsed; } + + public MenuItemImpl getExpandedItem() { + return mExpandedItem; + } } diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index 626561894bfc..329b457b56c9 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -18,6 +18,7 @@ package com.android.internal.view.menu; import android.content.Context; import android.content.res.Resources; +import android.database.DataSetObserver; import android.os.Parcelable; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -286,22 +287,45 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On return false; } + @Override + public int getId() { + return 0; + } + + @Override + public Parcelable onSaveInstanceState() { + return null; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + } + private class MenuAdapter extends BaseAdapter { private MenuBuilder mAdapterMenu; + private int mExpandedIndex = -1; public MenuAdapter(MenuBuilder menu) { mAdapterMenu = menu; + registerDataSetObserver(new ExpandedIndexObserver()); + findExpandedIndex(); } public int getCount() { ArrayList<MenuItemImpl> items = mOverflowOnly ? mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); - return items.size(); + if (mExpandedIndex < 0) { + return items.size(); + } + return items.size() - 1; } public MenuItemImpl getItem(int position) { ArrayList<MenuItemImpl> items = mOverflowOnly ? mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); + if (mExpandedIndex >= 0 && position >= mExpandedIndex) { + position++; + } return items.get(position); } @@ -323,19 +347,28 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On itemView.initialize(getItem(position), 0); return convertView; } - } - - @Override - public int getId() { - return 0; - } - @Override - public Parcelable onSaveInstanceState() { - return null; + void findExpandedIndex() { + final MenuItemImpl expandedItem = mMenu.getExpandedItem(); + if (expandedItem != null) { + final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); + final int count = items.size(); + for (int i = 0; i < count; i++) { + final MenuItemImpl item = items.get(i); + if (item == expandedItem) { + mExpandedIndex = i; + return; + } + } + } + mExpandedIndex = -1; + } } - @Override - public void onRestoreInstanceState(Parcelable state) { + private class ExpandedIndexObserver extends DataSetObserver { + @Override + public void onChanged() { + mAdapter.findExpandedIndex(); + } } } diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java index 6c11288deb61..06f5158f43e4 100644 --- a/core/java/com/android/internal/widget/AbsActionBarView.java +++ b/core/java/com/android/internal/widget/AbsActionBarView.java @@ -35,6 +35,8 @@ public abstract class AbsActionBarView extends ViewGroup { protected ActionMenuView mMenuView; protected ActionMenuPresenter mActionMenuPresenter; protected ActionBarContainer mSplitView; + protected boolean mSplitActionBar; + protected boolean mSplitWhenNarrow; protected int mContentHeight; protected Animator mVisibilityAnim; @@ -66,11 +68,31 @@ public abstract class AbsActionBarView extends ViewGroup { com.android.internal.R.attr.actionBarStyle, 0); setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0)); a.recycle(); + if (mSplitWhenNarrow) { + setSplitActionBar(getContext().getResources().getBoolean( + com.android.internal.R.bool.split_action_bar_is_narrow)); + } if (mActionMenuPresenter != null) { mActionMenuPresenter.onConfigurationChanged(newConfig); } } + /** + * Sets whether the bar should be split right now, no questions asked. + * @param split true if the bar should split + */ + public void setSplitActionBar(boolean split) { + mSplitActionBar = split; + } + + /** + * Sets whether the bar should split if we enter a narrow screen configuration. + * @param splitWhenNarrow true if the bar should check to split after a config change + */ + public void setSplitWhenNarrow(boolean splitWhenNarrow) { + mSplitWhenNarrow = splitWhenNarrow; + } + public void setContentHeight(int height) { mContentHeight = height; requestLayout(); diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 7bc33c73baab..acffa5c16d1b 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -93,6 +93,39 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi a.recycle(); } + @Override + public void setSplitActionBar(boolean split) { + if (mSplitActionBar != split) { + if (mActionMenuPresenter != null) { + // Mode is already active; move everything over and adjust the menu itself. + final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.MATCH_PARENT); + if (!split) { + mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + mMenuView.setBackgroundDrawable(null); + final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); + if (oldParent != null) oldParent.removeView(mMenuView); + addView(mMenuView, layoutParams); + } else { + // Allow full screen width in split mode. + mActionMenuPresenter.setWidthLimit( + getContext().getResources().getDisplayMetrics().widthPixels, true); + // No limit to the item count; use whatever will fit. + mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); + // Span the whole width + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = mContentHeight; + mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + mMenuView.setBackgroundDrawable(mSplitBackground); + final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); + if (oldParent != null) oldParent.removeView(mMenuView); + mSplitView.addView(mMenuView, layoutParams); + } + } + super.setSplitActionBar(split); + } + } + public void setContentHeight(int height) { mContentHeight = height; } @@ -179,7 +212,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); - if (mSplitView == null) { + if (!mSplitActionBar) { menu.addMenuPresenter(mActionMenuPresenter); mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); mMenuView.setBackgroundDrawable(null); diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index bbecb6c89af4..6d2e8232156b 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -113,7 +113,6 @@ public class ActionBarView extends AbsActionBarView { private int mProgressStyle; private int mIndeterminateProgressStyle; - private boolean mSplitActionBar; private boolean mUserTitle; private boolean mIncludeTabs; private boolean mIsCollapsable; @@ -133,6 +132,8 @@ public class ActionBarView extends AbsActionBarView { private ExpandedActionViewMenuPresenter mExpandedMenuPresenter; View mExpandedActionView; + Window.Callback mWindowCallback; + private final AdapterView.OnItemSelectedListener mNavItemSelectedListener = new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView parent, View view, int position, long id) { @@ -157,11 +158,7 @@ public class ActionBarView extends AbsActionBarView { private final OnClickListener mUpClickListener = new OnClickListener() { public void onClick(View v) { - Context context = getContext(); - if (context instanceof Activity) { - Activity activity = (Activity) context; - activity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem); - } + mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem); } }; @@ -276,6 +273,14 @@ public class ActionBarView extends AbsActionBarView { } } + /** + * Set the window callback used to invoke menu items; used for dispatching home button presses. + * @param cb Window callback to dispatch to + */ + public void setWindowCallback(Window.Callback cb) { + mWindowCallback = cb; + } + @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); @@ -301,6 +306,7 @@ public class ActionBarView extends AbsActionBarView { addView(mIndeterminateProgressView); } + @Override public void setSplitActionBar(boolean splitActionBar) { if (mSplitActionBar != splitActionBar) { if (mMenuView != null) { @@ -316,7 +322,10 @@ public class ActionBarView extends AbsActionBarView { addView(mMenuView); } } - mSplitActionBar = splitActionBar; + if (mSplitView != null) { + mSplitView.setVisibility(splitActionBar ? VISIBLE : GONE); + } + super.setSplitActionBar(splitActionBar); } } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 76550cf35eb7..4a38775a32a6 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -23,6 +23,7 @@ import com.google.android.collect.Lists; import android.app.admin.DevicePolicyManager; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; import android.os.FileObserver; import android.os.IBinder; import android.os.RemoteException; @@ -371,7 +372,8 @@ public class LockPatternUtils { /** * Clear any lock pattern or password. */ - public void clearLock() { + public void clearLock(boolean isFallback) { + if(!isFallback) deleteGallery(); saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); setLockPatternEnabled(false); saveLockPattern(null); @@ -408,6 +410,39 @@ public class LockPatternUtils { } /** + * Calls back SetupFaceLock to save the temporary gallery file if this is the backup lock. + * This doesn't have to verify that biometric is enabled because it's only called in that case + */ + void moveTempGallery() { + Intent intent = new Intent().setClassName("com.android.facelock", + "com.android.facelock.SetupFaceLock"); + intent.putExtra("moveTempGallery", true); + mContext.startActivity(intent); + } + + /** + * Calls back SetupFaceLock to delete the temporary gallery file + */ + public void deleteTempGallery() { + Intent intent = new Intent().setClassName("com.android.facelock", + "com.android.facelock.SetupFaceLock"); + intent.putExtra("deleteTempGallery", true); + mContext.startActivity(intent); + } + + /** + * Calls back SetupFaceLock to delete the gallery file when the lock type is changed + */ + void deleteGallery() { + if(isBiometricEnabled()) { + Intent intent = new Intent().setClassName("com.android.facelock", + "com.android.facelock.SetupFaceLock"); + intent.putExtra("deleteGallery", true); + mContext.startActivity(intent); + } + } + + /** * Save a lock pattern. * @param pattern The new pattern to save. * @param isFallback Specifies if this is a fallback to biometric weak @@ -431,11 +466,13 @@ public class LockPatternUtils { keyStore.password(patternToString(pattern)); setBoolean(PATTERN_EVER_CHOSEN_KEY, true); if (!isFallback) { + deleteGallery(); setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); } else { setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); + moveTempGallery(); } dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern .size(), 0, 0, 0, 0, 0, 0); @@ -547,10 +584,12 @@ public class LockPatternUtils { int computedQuality = computePasswordQuality(password); if (!isFallback) { + deleteGallery(); setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality)); } else { setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality)); + moveTempGallery(); } if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { int letters = 0; @@ -947,18 +986,24 @@ public class LockPatternUtils { * * If there's currently a call in progress, the button will take them to the call * @param button the button to update + * @param the phone state: + * {@link TelephonyManager#CALL_STATE_IDLE} + * {@link TelephonyManager#CALL_STATE_RINGING} + * {@link TelephonyManager#CALL_STATE_OFFHOOK} + * @param showIfCapable indicates whether the button should be shown if emergency calls are + * possible on the device */ - public void updateEmergencyCallButtonState(Button button) { - if (isEmergencyCallCapable()) { + public void updateEmergencyCallButtonState(Button button, int phoneState, + boolean showIfCapable) { + if (isEmergencyCallCapable() && showIfCapable) { button.setVisibility(View.VISIBLE); } else { button.setVisibility(View.GONE); return; } - int newState = TelephonyManager.getDefault().getCallState(); int textId; - if (newState == TelephonyManager.CALL_STATE_OFFHOOK) { + if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) { // show "return to call" text and show phone icon textId = R.string.lockscreen_return_to_call; int phoneCallIcon = R.drawable.stat_sys_phone_call; @@ -988,22 +1033,4 @@ public class LockPatternUtils { } return false; } - - /** - * Performs concentenation of PLMN/SPN - * @param plmn - * @param spn - * @return - */ - public static CharSequence getCarrierString(CharSequence plmn, CharSequence spn) { - if (plmn != null && spn == null) { - return plmn; - } else if (plmn != null && spn != null) { - return plmn + "|" + spn; - } else if (plmn == null && spn != null) { - return spn; - } else { - return ""; - } - } } diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java index cc2ed7ffb807..ebd355aa272c 100644 --- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java +++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java @@ -71,7 +71,7 @@ public class MultiWaveView extends View { // Tune-able parameters private static final int CHEVRON_INCREMENTAL_DELAY = 160; - private static final int CHEVRON_ANIMATION_DURATION = 650; + private static final int CHEVRON_ANIMATION_DURATION = 850; private static final int RETURN_TO_HOME_DELAY = 1200; private static final int RETURN_TO_HOME_DURATION = 300; private static final int HIDE_ANIMATION_DELAY = 200; @@ -114,6 +114,13 @@ public class MultiWaveView extends View { } }; + private AnimatorListener mResetListenerWithPing = new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animator) { + ping(); + switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY); + } + }; + private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { invalidateGlobalRegion(mHandleDrawable); @@ -297,7 +304,7 @@ public class MultiWaveView extends View { */ private void startChevronAnimation() { final float r = mHandleDrawable.getWidth() * 0.4f; - final float chevronAnimationDistance = mOuterRadius * 0.8f; + final float chevronAnimationDistance = mOuterRadius * 0.9f; final float from[][] = { {mWaveCenterX - r, mWaveCenterY}, // left {mWaveCenterX + r, mWaveCenterY}, // right @@ -310,6 +317,8 @@ public class MultiWaveView extends View { {mWaveCenterX, mWaveCenterY + chevronAnimationDistance} }; // bottom mChevronAnimations.clear(); + final float startScale = 0.5f; + final float endScale = 2.0f; for (int direction = 0; direction < 4; direction++) { for (int count = 0; count < mFeedbackCount; count++) { int delay = count * CHEVRON_INCREMENTAL_DELAY; @@ -323,6 +332,8 @@ public class MultiWaveView extends View { "x", new float[] { from[direction][0], to[direction][0] }, "y", new float[] { from[direction][1], to[direction][1] }, "alpha", new float[] {1.0f, 0.0f}, + "scaleX", new float[] {startScale, endScale}, + "scaleY", new float[] {startScale, endScale}, "onUpdate", mUpdateListener)); } } @@ -417,7 +428,7 @@ public class MultiWaveView extends View { "x", mWaveCenterX, "y", mWaveCenterY, "onUpdate", mUpdateListener, - "onComplete", mResetListener); + "onComplete", mDragging ? mResetListenerWithPing : mResetListener); } setGrabbedState(OnTriggerListener.NO_HANDLE); diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/core/java/com/google/android/mms/pdu/PduPersister.java index 4d2d535444f7..c4be51328997 100644 --- a/core/java/com/google/android/mms/pdu/PduPersister.java +++ b/core/java/com/google/android/mms/pdu/PduPersister.java @@ -667,6 +667,13 @@ public class PduPersister { String contentType = null; if (part.getContentType() != null) { contentType = toIsoString(part.getContentType()); + + // There is no "image/jpg" in Android (and it's an invalid mimetype). + // Change it to "image/jpeg" + if (ContentType.IMAGE_JPG.equals(contentType)) { + contentType = ContentType.IMAGE_JPEG; + } + values.put(Part.CONTENT_TYPE, contentType); // To ensure the SMIL part is always the first part. if (ContentType.APP_SMIL.equals(contentType)) { diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index 9313d0afce2b..02c5bb3a2885 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -758,21 +758,7 @@ public: jfloat x, jfloat y, int flags, SkPaint* paint) { jint count = end - start; - sp<TextLayoutCacheValue> value; -#if USE_TEXT_LAYOUT_CACHE - value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count, - end, flags); - if (value == NULL) { - LOGE("Cannot get TextLayoutCache value"); - return ; - } -#else - value = new TextLayoutCacheValue(); - value->computeValues(paint, textArray, start, count, end, flags); -#endif - - doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), - x, y, flags, paint); + drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint); } static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray, @@ -781,19 +767,20 @@ public: sp<TextLayoutCacheValue> value; #if USE_TEXT_LAYOUT_CACHE - value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count, - contextCount, flags); + value = TextLayoutCache::getInstance().getValue(paint, textArray, contextCount, flags); if (value == NULL) { LOGE("Cannot get TextLayoutCache value"); return ; } #else value = new TextLayoutCacheValue(); - value->computeValues(paint, textArray, start, count, contextCount, flags); + value->computeValues(paint, textArray, contextCount, flags); #endif - - doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), - x, y, flags, paint); + size_t startIndex = 0; + size_t glyphsCount = 0; + value->getGlyphsIndexAndCount(start, count, &startIndex, &glyphsCount); + const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount); + doDrawGlyphs(canvas, glyphs, 0, glyphsCount, x, y, flags, paint); } static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count, diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 7d222f639392..3daf7d0273cd 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -352,7 +352,7 @@ public: jfloat result = 0; #if RTL_USE_HARFBUZZ TextLayout::getTextRunAdvances(paint, textArray, index, count, textLength, - paint->getFlags(), NULL /* dont need all advances */, result); + paint->getFlags(), NULL /* dont need all advances */, &result); #else // we double count, since measureText wants a byteLength SkScalar width = paint->measureText(textArray + index, count << 1); @@ -382,7 +382,7 @@ public: #if RTL_USE_HARFBUZZ TextLayout::getTextRunAdvances(paint, textArray, start, count, textLength, - paint->getFlags(), NULL /* dont need all advances */, width); + paint->getFlags(), NULL /* dont need all advances */, &width); #else width = SkScalarToFloat(paint->measureText(textArray + start, count << 1)); @@ -406,7 +406,7 @@ public: #if RTL_USE_HARFBUZZ TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength, - paint->getFlags(), NULL /* dont need all advances */, width); + paint->getFlags(), NULL /* dont need all advances */, &width); #else width = SkScalarToFloat(paint->measureText(textArray, textLength << 1)); #endif @@ -435,10 +435,8 @@ public: jfloat* widthsArray = autoWidths.ptr(); #if RTL_USE_HARFBUZZ - jfloat totalAdvance; - TextLayout::getTextRunAdvances(paint, text, 0, count, count, - paint->getFlags(), widthsArray, totalAdvance); + paint->getFlags(), widthsArray, NULL /* dont need totalAdvance */); #else SkScalar* scalarArray = (SkScalar*)widthsArray; @@ -533,7 +531,7 @@ public: jfloat totalAdvance = 0; TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags, - advancesArray, totalAdvance); + advancesArray, &totalAdvance); if (advances != NULL) { env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray); @@ -604,10 +602,9 @@ public: jint count, jint flags, jint offset, jint opt) { #if RTL_USE_HARFBUZZ jfloat scalarArray[count]; - jfloat totalAdvance = 0; TextLayout::getTextRunAdvances(paint, text, start, count, count, flags, - scalarArray, totalAdvance); + scalarArray, NULL /* dont need totalAdvance */); #else SkScalar scalarArray[count]; jchar buffer[count]; diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp index a2d6efb5b03a..ae17aed1a8e0 100644 --- a/core/jni/android/graphics/TextLayout.cpp +++ b/core/jni/android/graphics/TextLayout.cpp @@ -253,21 +253,22 @@ void TextLayout::drawTextRun(SkPaint* paint, const jchar* chars, void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start, jint count, jint contextCount, jint dirFlags, - jfloat* resultAdvances, jfloat& resultTotalAdvance) { + jfloat* resultAdvances, jfloat* resultTotalAdvance) { sp<TextLayoutCacheValue> value; #if USE_TEXT_LAYOUT_CACHE // Return advances from the cache. Compute them if needed - value = TextLayoutCache::getInstance().getValue( - paint, chars, start, count, contextCount, dirFlags); + value = TextLayoutCache::getInstance().getValue(paint, chars, contextCount, dirFlags); #else value = new TextLayoutCacheValue(); - value->computeValues(paint, chars, start, count, contextCount, dirFlags); + value->computeValues(paint, chars, contextCount, dirFlags); #endif if (value != NULL) { if (resultAdvances != NULL) { - memcpy(resultAdvances, value->getAdvances(), value->getAdvancesCount() * sizeof(jfloat)); + value->getAdvances(start, count, resultAdvances); + } + if (resultTotalAdvance) { + *resultTotalAdvance = value->getTotalAdvance(start, count); } - resultTotalAdvance = value->getTotalAdvance(); } } diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h index 9d8913c74937..9df38296e329 100644 --- a/core/jni/android/graphics/TextLayout.h +++ b/core/jni/android/graphics/TextLayout.h @@ -71,7 +71,7 @@ public: static void getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start, jint count, jint contextCount, jint dirFlags, - jfloat* resultAdvances, jfloat& resultTotalAdvance); + jfloat* resultAdvances, jfloat* resultTotalAdvance); static void getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start, jint count, jint contextCount, jint dirFlags, diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index e4eeec8e08b4..86ae7d2ae05f 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -106,7 +106,7 @@ void TextLayoutCache::clear() { * Caching */ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, - const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) { + const jchar* text, jint count, jint dirFlags) { AutoMutex _l(mLock); nsecs_t startTime = 0; if (mDebugEnabled) { @@ -114,7 +114,7 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, } // Create the key - TextLayoutCacheKey key(paint, text, start, count, contextCount, dirFlags); + TextLayoutCacheKey key(paint, text, count, dirFlags); // Get value from cache if possible sp<TextLayoutCacheValue> value = mCache.get(key); @@ -128,7 +128,7 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, value = new TextLayoutCacheValue(); // Compute advances and store them - value->computeValues(paint, text, start, count, contextCount, dirFlags); + value->computeValues(paint, text, count, dirFlags); nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC); @@ -157,20 +157,20 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, // Update timing information for statistics value->setElapsedTime(endTime - startTime); - LOGD("CACHE MISS: Added entry with start=%d, count=%d, " - "contextCount=%d, entry size %d bytes, remaining space %d bytes" + LOGD("CACHE MISS: Added entry with " + "count=%d, entry size %d bytes, remaining space %d bytes" " - Compute time in nanos: %d - Text='%s' ", - start, count, contextCount, size, mMaxSize - mSize, value->getElapsedTime(), - String8(text, contextCount).string()); + count, size, mMaxSize - mSize, value->getElapsedTime(), + String8(text, count).string()); } } else { if (mDebugEnabled) { LOGD("CACHE MISS: Calculated but not storing entry because it is too big " - "with start=%d, count=%d, contextCount=%d, " + "with count=%d, " "entry size %d bytes, remaining space %d bytes" " - Compute time in nanos: %lld - Text='%s'", - start, count, contextCount, size, mMaxSize - mSize, endTime, - String8(text, contextCount).string()); + count, size, mMaxSize - mSize, endTime, + String8(text, count).string()); } value.clear(); } @@ -184,12 +184,12 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, if (value->getElapsedTime() > 0) { float deltaPercent = 100 * ((value->getElapsedTime() - elapsedTimeThruCacheGet) / ((float)value->getElapsedTime())); - LOGD("CACHE HIT #%d with start=%d, count=%d, contextCount=%d " + LOGD("CACHE HIT #%d with count=%d " "- Compute time in nanos: %d - " "Cache get time in nanos: %lld - Gain in percent: %2.2f - Text='%s' ", - mCacheHitCount, start, count, contextCount, + mCacheHitCount, count, value->getElapsedTime(), elapsedTimeThruCacheGet, deltaPercent, - String8(text, contextCount).string()); + String8(text, count).string()); } if (mCacheHitCount % DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL == 0) { dumpCacheStats(); @@ -218,15 +218,14 @@ void TextLayoutCache::dumpCacheStats() { /** * TextLayoutCacheKey */ -TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0), +TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), count(0), dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0), hinting(SkPaint::kNo_Hinting) { } TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, - const UChar* text, size_t start, size_t count, - size_t contextCount, int dirFlags) : - text(text), start(start), count(count), contextCount(contextCount), + const UChar* text, size_t count, int dirFlags) : + text(text), count(count), dirFlags(dirFlags) { typeface = paint->getTypeface(); textSize = paint->getTextSize(); @@ -239,9 +238,7 @@ TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) : text(NULL), textCopy(other.textCopy), - start(other.start), count(other.count), - contextCount(other.contextCount), dirFlags(other.dirFlags), typeface(other.typeface), textSize(other.textSize), @@ -256,18 +253,15 @@ TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) : bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const { LTE_INT(count) { - LTE_INT(contextCount) { - LTE_INT(start) { - LTE_INT(typeface) { - LTE_FLOAT(textSize) { - LTE_FLOAT(textSkewX) { - LTE_FLOAT(textScaleX) { - LTE_INT(flags) { - LTE_INT(hinting) { - LTE_INT(dirFlags) { - return strncmp16(getText(), rhs.getText(), contextCount) < 0; - } - } + LTE_INT(typeface) { + LTE_FLOAT(textSize) { + LTE_FLOAT(textSkewX) { + LTE_FLOAT(textScaleX) { + LTE_INT(flags) { + LTE_INT(hinting) { + LTE_INT(dirFlags) { + return memcmp(getText(), rhs.getText(), + count * sizeof(UChar)) < 0; } } } @@ -280,12 +274,12 @@ bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const { } void TextLayoutCacheKey::internalTextCopy() { - textCopy.setTo(text, contextCount); + textCopy.setTo(text, count); text = NULL; } size_t TextLayoutCacheKey::getSize() { - return sizeof(TextLayoutCacheKey) + sizeof(UChar) * contextCount; + return sizeof(TextLayoutCacheKey) + sizeof(UChar) * count; } /** @@ -303,23 +297,23 @@ uint32_t TextLayoutCacheValue::getElapsedTime() { return mElapsedTime; } -void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars, size_t start, - size_t count, size_t contextCount, int dirFlags) { - // Give a hint for advances and glyphs vectors size - mAdvances.setCapacity(count); - mGlyphs.setCapacity(count); - computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, - &mAdvances, &mTotalAdvance, &mGlyphs); +void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars, + size_t contextCount, int dirFlags) { + // Give a hint for advances, glyphs and log clusters vectors size + mAdvances.setCapacity(contextCount); + mGlyphs.setCapacity(contextCount); + mLogClusters.setCapacity(contextCount); + + computeValuesWithHarfbuzz(paint, chars, contextCount, dirFlags, + &mAdvances, &mTotalAdvance, &mGlyphs, &mLogClusters); #if DEBUG_ADVANCES - LOGD("Advances - count=%d - countextCount=%d - totalAdvance=%f - " - "adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, mTotalAdvance, - mAdvances[0], mAdvances[1], mAdvances[2], mAdvances[3]); + LOGD("Advances - countextCount=%d - totalAdvance=%f", contextCount, mTotalAdvance); #endif } size_t TextLayoutCacheValue::getSize() { return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * mAdvances.capacity() + - sizeof(jchar) * mGlyphs.capacity(); + sizeof(jchar) * mGlyphs.capacity() + sizeof(unsigned short) * mLogClusters.capacity(); } void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, @@ -391,9 +385,9 @@ void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontR } void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, - size_t start, size_t count, size_t contextCount, int dirFlags, + size_t contextCount, int dirFlags, Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, - Vector<jchar>* const outGlyphs) { + Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters) { UBiDiLevel bidiReq = 0; bool forceLTR = false; @@ -413,8 +407,8 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d", forceLTR, forceRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, forceRTL, - outAdvances, outTotalAdvance, outGlyphs); + computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount, forceRTL, + outAdvances, outTotalAdvance, outGlyphs, outLogClusters); } else { UBiDi* bidi = ubidi_open(); if (bidi) { @@ -433,35 +427,16 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar bool isRTL = (paraDir == 1); #if DEBUG_GLYPHS LOGD("computeValuesWithHarfbuzz -- processing SINGLE run " - "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL); + "-- run-start=%d run-len=%d isRTL=%d", 0, contextCount, isRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, - isRTL, outAdvances, outTotalAdvance, outGlyphs); + computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount, + isRTL, outAdvances, outTotalAdvance, outGlyphs, outLogClusters); } else { - int32_t end = start + count; for (size_t i = 0; i < rc; ++i) { int32_t startRun; int32_t lengthRun; UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun); - if (startRun >= end) { - break; - } - - int32_t endRun = startRun + lengthRun; - if (endRun <= start) { - continue; - } - - if (startRun < start) { - startRun = start; - } - if (endRun > end) { - endRun = end; - } - - lengthRun = endRun - startRun; - bool isRTL = (runDir == UBIDI_RTL); jfloat runTotalAdvance = 0; #if DEBUG_GLYPHS @@ -471,7 +446,7 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar computeRunValuesWithHarfbuzz(paint, chars, startRun, lengthRun, contextCount, isRTL, outAdvances, &runTotalAdvance, - outGlyphs); + outGlyphs, outLogClusters); *outTotalAdvance += runTotalAdvance; } @@ -483,10 +458,10 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar bool isRTL = (bidiReq = 1) || (bidiReq = UBIDI_DEFAULT_RTL); #if DEBUG_GLYPHS LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering a SINGLE Run " - "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL); + "-- run-start=%d run-len=%d isRTL=%d", 0, contextCount, isRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, isRTL, - outAdvances, outTotalAdvance, outGlyphs); + computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount, isRTL, + outAdvances, outTotalAdvance, outGlyphs, outLogClusters); } } #if DEBUG_GLYPHS @@ -506,7 +481,7 @@ static void logGlyphs(HB_ShaperItem shaperItem) { void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, bool isRTL, Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, - Vector<jchar>* const outGlyphs) { + Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters) { HB_ShaperItem shaperItem; HB_FontRec font; @@ -557,15 +532,15 @@ void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UC #if DEBUG_ADVANCES for (size_t i = 0; i < count; i++) { LOGD("hb-adv[%d] = %f - log_clusters = %d - total = %f", i, - outAdvances[i], shaperItem.log_clusters[i], totalAdvance); + (*outAdvances)[i], shaperItem.log_clusters[i], totalAdvance); } #endif // Get Glyphs and reverse them in place if RTL if (outGlyphs) { - size_t count = shaperItem.num_glyphs; - for (size_t i = 0; i < count; i++) { - jchar glyph = (jchar) shaperItem.glyphs[(!isRTL) ? i : count - 1 - i]; + size_t countGlyphs = shaperItem.num_glyphs; + for (size_t i = 0; i < countGlyphs; i++) { + jchar glyph = (jchar) shaperItem.glyphs[(!isRTL) ? i : countGlyphs - 1 - i]; #if DEBUG_GLYPHS LOGD("HARFBUZZ -- glyph[%d]=%d", i, glyph); #endif @@ -573,6 +548,19 @@ void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UC } } + // Get LogClusters + if (outLogClusters) { + size_t countLogClusters = outLogClusters->size(); + for (size_t i = 0; i < count; i++) { + // As there may be successive runs, we need to shift the log clusters + unsigned short logCluster = shaperItem.log_clusters[i] + countLogClusters; +#if DEBUG_GLYPHS + LOGD("HARFBUZZ -- logCluster[%d] relative=%d - absolute=%d", i, shaperItem.log_clusters[i], logCluster); +#endif + outLogClusters->add(logCluster); + } + } + // Cleaning deleteGlyphArrays(&shaperItem); HB_FreeFace(shaperItem.face); @@ -603,5 +591,57 @@ void TextLayoutCacheValue::resetGlyphArrays(HB_ShaperItem* shaperItem) { memset(shaperItem->offsets, 0, size * sizeof(shaperItem->offsets[0])); } +void TextLayoutCacheValue::getAdvances(size_t start, size_t count, jfloat* outAdvances) const { + memcpy(outAdvances, mAdvances.array() + start, count * sizeof(jfloat)); +#if DEBUG_ADVANCES + LOGD("getAdvances - start=%d count=%d", start, count); + for (size_t i = 0; i < count; i++) { + LOGD(" adv[%d] = %f", i, outAdvances[i]); + } +#endif +} + +jfloat TextLayoutCacheValue::getTotalAdvance(size_t start, size_t count) const { + jfloat outTotalAdvance = 0; + for (size_t i = start; i < start + count; i++) { + outTotalAdvance += mAdvances[i]; + } +#if DEBUG_ADVANCES + LOGD("getTotalAdvance - start=%d count=%d - total=%f", start, count, outTotalAdvance); +#endif + return outTotalAdvance; +} + +void TextLayoutCacheValue::getGlyphsIndexAndCount(size_t start, size_t count, size_t* outStartIndex, + size_t* outGlyphsCount) const { + *outStartIndex = 0; + if (count == 0) { + *outGlyphsCount = 0; + return; + } + *outStartIndex = mLogClusters[start]; + *outGlyphsCount = mLogClusters[start + count - 1] - mLogClusters[start] + 1; +#if DEBUG_GLYPHS + LOGD("getGlyphsIndexes - start=%d count=%d - startIndex=%d count=%d", start, count, + *outStartIndex, *outGlyphsCount); + for(size_t i = 0; i < mGlyphs.size(); i++) { + LOGD("getGlyphs - all - glyph[%d] = %d", i, mGlyphs[i]); + } + for(size_t i = 0; i < mAdvances.size(); i++) { + LOGD("getGlyphs - all - logcl[%d] = %d", i, mLogClusters[i]); + } +#endif +} + +const jchar* TextLayoutCacheValue::getGlyphs(size_t startIndex, size_t count) { + const jchar* glyphs = mGlyphs.array() + startIndex; +#if DEBUG_GLYPHS + LOGD("getGlyphs - with startIndex = %d count = %d", startIndex, count); + for (size_t i = 0; i < count; i++) { + LOGD("getGlyphs - result - glyph[%d] = %d", i, glyphs[i]); + } +#endif + return glyphs; +} } // namespace android diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index 1f08bda07f5e..35dd6fd8ed17 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -68,9 +68,7 @@ class TextLayoutCacheKey { public: TextLayoutCacheKey(); - TextLayoutCacheKey(const SkPaint* paint, - const UChar* text, size_t start, size_t count, - size_t contextCount, int dirFlags); + TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t count, int dirFlags); TextLayoutCacheKey(const TextLayoutCacheKey& other); @@ -90,9 +88,7 @@ public: private: const UChar* text; // if text is NULL, use textCopy String16 textCopy; - size_t start; size_t count; - size_t contextCount; int dirFlags; SkTypeface* typeface; SkScalar textSize; @@ -116,14 +112,13 @@ public: void setElapsedTime(uint32_t time); uint32_t getElapsedTime(); - void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count, - size_t contextCount, int dirFlags); + void computeValues(SkPaint* paint, const UChar* chars, size_t contextCount, int dirFlags); - inline const jfloat* getAdvances() const { return mAdvances.array(); } - inline size_t getAdvancesCount() const { return mAdvances.size(); } - inline jfloat getTotalAdvance() const { return mTotalAdvance; } - inline const jchar* getGlyphs() const { return mGlyphs.array(); } - inline size_t getGlyphsCount() const { return mGlyphs.size(); } + void getAdvances(size_t start, size_t count, jfloat* outAdvances) const; + jfloat getTotalAdvance(size_t start, size_t count) const; + void getGlyphsIndexAndCount(size_t start, size_t count, size_t* outStartIndex, + size_t* outGlyphsCount) const; + const jchar* getGlyphs(size_t startIndex, size_t count); /** * Get the size of the Cache entry @@ -138,14 +133,10 @@ public: SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, bool isRTL); - static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, - size_t count, size_t contextCount, int dirFlags, + static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, + size_t contextCount, int dirFlags, Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, - Vector<jchar>* const outGlyphs); - - static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start, - size_t count, size_t contextCount, int dirFlags, - jfloat* outAdvances, jfloat* outTotalAdvance); + Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters); private: /** @@ -164,6 +155,11 @@ private: Vector<jchar> mGlyphs; /** + * Harfbuzz Log Clusters + */ + Vector<unsigned short> mLogClusters; + + /** * Time for computing the values (in milliseconds) */ uint32_t mElapsedTime; @@ -175,7 +171,7 @@ private: static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, bool isRTL, Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, - Vector<jchar>* const outGlyphs); + Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters); }; // TextLayoutCacheValue /** @@ -199,8 +195,8 @@ public: */ void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc); - sp<TextLayoutCacheValue> getValue(SkPaint* paint, - const jchar* text, jint start, jint count, jint contextCount, jint dirFlags); + sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint count, + jint dirFlags); /** * Clear the cache diff --git a/core/jni/android_app_backup_FullBackup.cpp b/core/jni/android_app_backup_FullBackup.cpp index b36fa3e2f6b2..6ef62a9824f1 100644 --- a/core/jni/android_app_backup_FullBackup.cpp +++ b/core/jni/android_app_backup_FullBackup.cpp @@ -76,10 +76,10 @@ static int backupToTar(JNIEnv* env, jobject clazz, jstring packageNameObj, int ret; // Extract the various strings, allowing for null object pointers - const char* packagenamechars = env->GetStringUTFChars(packageNameObj, NULL); - const char* rootchars = env->GetStringUTFChars(rootpathObj, NULL); - const char* pathchars = env->GetStringUTFChars(pathObj, NULL); - const char* domainchars = env->GetStringUTFChars(domainObj, NULL); + const char* packagenamechars = (packageNameObj) ? env->GetStringUTFChars(packageNameObj, NULL) : NULL; + const char* rootchars = (rootpathObj) ? env->GetStringUTFChars(rootpathObj, NULL) : NULL; + const char* pathchars = (pathObj) ? env->GetStringUTFChars(pathObj, NULL) : NULL; + const char* domainchars = (domainObj) ? env->GetStringUTFChars(domainObj, NULL) : NULL; String8 packageName(packagenamechars ? packagenamechars : ""); String8 rootpath(rootchars ? rootchars : ""); diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp index 84a50f029e67..84c636b0ede5 100644 --- a/core/jni/android_net_wifi_Wifi.cpp +++ b/core/jni/android_net_wifi_Wifi.cpp @@ -402,30 +402,6 @@ static jint android_net_wifi_getRssiHelper(const char *cmd) return (jint)rssi; } -static jint android_net_wifi_getRssiCommand(JNIEnv* env, jobject) -{ - return android_net_wifi_getRssiHelper("DRIVER RSSI"); -} - -static jint android_net_wifi_getRssiApproxCommand(JNIEnv* env, jobject) -{ - return android_net_wifi_getRssiHelper("DRIVER RSSI-APPROX"); -} - -static jint android_net_wifi_getLinkSpeedCommand(JNIEnv* env, jobject) -{ - char reply[BUF_SIZE]; - int linkspeed; - - if (doCommand("DRIVER LINKSPEED", reply, sizeof(reply)) != 0) { - return (jint)-1; - } - // reply comes back in the form "LinkSpeed XX" where XX is the - // number we're interested in. - sscanf(reply, "%*s %u", &linkspeed); - return (jint)linkspeed; -} - static jstring android_net_wifi_getMacAddressCommand(JNIEnv* env, jobject) { char reply[BUF_SIZE]; @@ -625,10 +601,6 @@ static JNINativeMethod gWifiMethods[] = { (void*) android_net_wifi_setBluetoothCoexistenceModeCommand }, { "setBluetoothCoexistenceScanModeCommand", "(Z)Z", (void*) android_net_wifi_setBluetoothCoexistenceScanModeCommand }, - { "getRssiCommand", "()I", (void*) android_net_wifi_getRssiCommand }, - { "getRssiApproxCommand", "()I", - (void*) android_net_wifi_getRssiApproxCommand}, - { "getLinkSpeedCommand", "()I", (void*) android_net_wifi_getLinkSpeedCommand }, { "getMacAddressCommand", "()Ljava/lang/String;", (void*) android_net_wifi_getMacAddressCommand }, { "saveConfigCommand", "()Z", (void*) android_net_wifi_saveConfigCommand }, { "reloadConfigCommand", "()Z", (void*) android_net_wifi_reloadConfigCommand }, diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 395e417aee39..e542a4717b88 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -477,19 +477,21 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count, #if RTL_USE_HARFBUZZ sp<TextLayoutCacheValue> value; #if USE_TEXT_LAYOUT_CACHE - value = TextLayoutCache::getInstance().getValue(paint, text, 0, count, count, flags); + value = TextLayoutCache::getInstance().getValue(paint, text, count, flags); if (value == NULL) { LOGE("Cannot get TextLayoutCache value"); return ; } #else value = new TextLayoutCacheValue(); - value->computeValues(paint, text, 0, count, count, flags); + value->computeValues(paint, text, count, flags); #endif - const jchar* glyphArray = value->getGlyphs(); - int glyphCount = value->getGlyphsCount(); - int bytesCount = glyphCount * sizeof(jchar); - renderer->drawText((const char*) glyphArray, bytesCount, glyphCount, x, y, paint); + size_t startIndex = 0; + size_t glyphsCount = 0; + value->getGlyphsIndexAndCount(0, count, &startIndex, &glyphsCount); + const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount); + int bytesCount = glyphsCount * sizeof(jchar); + renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint); #else const jchar *workText; jchar* buffer = NULL; @@ -507,19 +509,21 @@ static void renderTextRun(OpenGLRenderer* renderer, const jchar* text, #if RTL_USE_HARFBUZZ sp<TextLayoutCacheValue> value; #if USE_TEXT_LAYOUT_CACHE - value = TextLayoutCache::getInstance().getValue(paint, text, start, count, contextCount, flags); + value = TextLayoutCache::getInstance().getValue(paint, text, contextCount, flags); if (value == NULL) { LOGE("Cannot get TextLayoutCache value"); return ; } #else value = new TextLayoutCacheValue(); - value->computeValues(paint, text, start, count, contextCount, flags); + value->computeValues(paint, text, contextCount, flags); #endif - const jchar* glyphArray = value->getGlyphs(); - int glyphCount = value->getGlyphsCount(); - int bytesCount = glyphCount * sizeof(jchar); - renderer->drawText((const char*) glyphArray, bytesCount, glyphCount, x, y, paint); + size_t startIndex = 0; + size_t glyphsCount = 0; + value->getGlyphsIndexAndCount(start, count, &startIndex, &glyphsCount); + const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount); + int bytesCount = glyphsCount * sizeof(jchar); + renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint); #else uint8_t rtl = flags & 0x1; if (rtl) { diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png Binary files differindex 671ca318da41..52a9800130a6 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png Binary files differindex b024da420760..49a2aeb42313 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png Binary files differindex cba1ff5da67f..e6ebb43fbcec 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png Binary files differindex 62537b0e19c8..7069fc5b5623 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png Binary files differindex 5d559e114879..ec2a7e30f014 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png Binary files differindex 5041ff99309d..486334f7c8a6 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo.png b/core/res/res/drawable-hdpi/btn_check_on_holo.png Binary files differindex 4c1bfbcb27ab..1f11a7867580 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_holo.png +++ b/core/res/res/drawable-hdpi/btn_check_on_holo.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png Binary files differindex 3492b8a1fc48..a17100cf5007 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png Binary files differindex 49e837c6e5b2..130ab4f24596 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png Binary files differindex 0d4e8b30ab13..96abcda92024 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png Binary files differindex c4283b65b7f1..0a22f02a9cd4 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png Binary files differindex 94098902e928..28b25781b7da 100644 --- a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png +++ b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png diff --git a/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png Binary files differindex 55acc9ae968d..66cb1eca1c05 100644 --- a/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png +++ b/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png diff --git a/core/res/res/drawable-hdpi/btn_group_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_focused_holo_dark.9.png Binary files differindex 34762f8cc252..824b45ac7d4b 100644 --- a/core/res/res/drawable-hdpi/btn_group_focused_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/btn_group_focused_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/btn_group_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_focused_holo_light.9.png Binary files differindex 34762f8cc252..824b45ac7d4b 100644 --- a/core/res/res/drawable-hdpi/btn_group_focused_holo_light.9.png +++ b/core/res/res/drawable-hdpi/btn_group_focused_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/btn_group_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_pressed_holo_dark.9.png Binary files differindex 0d2eb4b990d5..34ec825d9e6c 100644 --- a/core/res/res/drawable-hdpi/btn_group_pressed_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/btn_group_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/btn_group_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_pressed_holo_light.9.png Binary files differindex 7de8d9be4ca6..f7680ab862db 100644 --- a/core/res/res/drawable-hdpi/btn_group_pressed_holo_light.9.png +++ b/core/res/res/drawable-hdpi/btn_group_pressed_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png Binary files differindex 3c1001495999..8906c4d86c15 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png Binary files differindex 93177761c23c..2bcb98ede035 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png Binary files differindex 8e92f715bb38..2e36821d5300 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png Binary files differindex 54ec8ee7cb2f..6a50bd82dada 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png Binary files differindex cdb1f71f37eb..8595dd0025f5 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png Binary files differindex ff7848decff6..1dda090f8afd 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png Binary files differindex 98705f777cf6..942722e29582 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png Binary files differindex 0d3147f579ae..e46f035313ad 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png Binary files differindex 01c54e69e95b..5cfe146716ae 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png Binary files differindex fe3225fcb7b8..20d0eb3c0bec 100644 --- a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png Binary files differindex c25fe90dff81..3b478d63375d 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png Binary files differindex 4185d719cbe8..52a9f442ea9b 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png Binary files differindex e95f4ab965d5..9810029e50f1 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png Binary files differindex 7ed0fab91897..445af7bd35a0 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png Binary files differindex c9e99e8237c2..d3884f618b96 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png Binary files differindex f8a36b331747..eea174aacd86 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_dark.png Binary files differindex 8bfd65abd214..fecb1afc7686 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png Binary files differindex ba942947e84b..58b2b0989364 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png Binary files differindex 9112ed6b455f..a39a6200b7ed 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png +++ b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png diff --git a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png Binary files differindex a29f69eb4463..1ffe7fe2c5a6 100644 --- a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png +++ b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png diff --git a/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png Binary files differindex a529487092c8..3dfe6c2eea81 100644 --- a/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png b/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png Binary files differindex e3641b5a8d59..ea38ebbb390c 100644 --- a/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png +++ b/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/emo_im_angel.png b/core/res/res/drawable-hdpi/emo_im_angel.png Binary files differindex e9d4983647ce..2cbb7dacedb4 100644 --- a/core/res/res/drawable-hdpi/emo_im_angel.png +++ b/core/res/res/drawable-hdpi/emo_im_angel.png diff --git a/core/res/res/drawable-hdpi/emo_im_cool.png b/core/res/res/drawable-hdpi/emo_im_cool.png Binary files differindex c8464b59c28a..3813bc6a278f 100644 --- a/core/res/res/drawable-hdpi/emo_im_cool.png +++ b/core/res/res/drawable-hdpi/emo_im_cool.png diff --git a/core/res/res/drawable-hdpi/emo_im_crying.png b/core/res/res/drawable-hdpi/emo_im_crying.png Binary files differindex 94a2b9a826c1..3982d7052f75 100644 --- a/core/res/res/drawable-hdpi/emo_im_crying.png +++ b/core/res/res/drawable-hdpi/emo_im_crying.png diff --git a/core/res/res/drawable-hdpi/emo_im_embarrassed.png b/core/res/res/drawable-hdpi/emo_im_embarrassed.png Binary files differindex fe9138db8bac..982f0ae215f0 100644 --- a/core/res/res/drawable-hdpi/emo_im_embarrassed.png +++ b/core/res/res/drawable-hdpi/emo_im_embarrassed.png diff --git a/core/res/res/drawable-hdpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-hdpi/emo_im_foot_in_mouth.png Binary files differindex 98471773d6f9..d40fb90d7ff2 100644 --- a/core/res/res/drawable-hdpi/emo_im_foot_in_mouth.png +++ b/core/res/res/drawable-hdpi/emo_im_foot_in_mouth.png diff --git a/core/res/res/drawable-hdpi/emo_im_happy.png b/core/res/res/drawable-hdpi/emo_im_happy.png Binary files differindex eba9debca83b..f1e47237f579 100644 --- a/core/res/res/drawable-hdpi/emo_im_happy.png +++ b/core/res/res/drawable-hdpi/emo_im_happy.png diff --git a/core/res/res/drawable-hdpi/emo_im_kissing.png b/core/res/res/drawable-hdpi/emo_im_kissing.png Binary files differindex ff19711a312f..21e5d304fd13 100644 --- a/core/res/res/drawable-hdpi/emo_im_kissing.png +++ b/core/res/res/drawable-hdpi/emo_im_kissing.png diff --git a/core/res/res/drawable-hdpi/emo_im_laughing.png b/core/res/res/drawable-hdpi/emo_im_laughing.png Binary files differindex b1d4d6a02ae1..03aa60a7794c 100644 --- a/core/res/res/drawable-hdpi/emo_im_laughing.png +++ b/core/res/res/drawable-hdpi/emo_im_laughing.png diff --git a/core/res/res/drawable-hdpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-hdpi/emo_im_lips_are_sealed.png Binary files differindex e47cf2ae8b98..14edaeb8e8e5 100644 --- a/core/res/res/drawable-hdpi/emo_im_lips_are_sealed.png +++ b/core/res/res/drawable-hdpi/emo_im_lips_are_sealed.png diff --git a/core/res/res/drawable-hdpi/emo_im_money_mouth.png b/core/res/res/drawable-hdpi/emo_im_money_mouth.png Binary files differindex 82f80f25e3d1..957bc906bfd8 100644 --- a/core/res/res/drawable-hdpi/emo_im_money_mouth.png +++ b/core/res/res/drawable-hdpi/emo_im_money_mouth.png diff --git a/core/res/res/drawable-hdpi/emo_im_sad.png b/core/res/res/drawable-hdpi/emo_im_sad.png Binary files differindex b5959ec8bac6..bcfe71b4c5d7 100644 --- a/core/res/res/drawable-hdpi/emo_im_sad.png +++ b/core/res/res/drawable-hdpi/emo_im_sad.png diff --git a/core/res/res/drawable-hdpi/emo_im_surprised.png b/core/res/res/drawable-hdpi/emo_im_surprised.png Binary files differindex dbe1c3873bcf..961a9bbfcfcf 100644 --- a/core/res/res/drawable-hdpi/emo_im_surprised.png +++ b/core/res/res/drawable-hdpi/emo_im_surprised.png diff --git a/core/res/res/drawable-hdpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-hdpi/emo_im_tongue_sticking_out.png Binary files differindex fb5f9adf0887..7a1235c78596 100644 --- a/core/res/res/drawable-hdpi/emo_im_tongue_sticking_out.png +++ b/core/res/res/drawable-hdpi/emo_im_tongue_sticking_out.png diff --git a/core/res/res/drawable-hdpi/emo_im_undecided.png b/core/res/res/drawable-hdpi/emo_im_undecided.png Binary files differindex b7edef7086f2..72bf2f2eddbd 100644 --- a/core/res/res/drawable-hdpi/emo_im_undecided.png +++ b/core/res/res/drawable-hdpi/emo_im_undecided.png diff --git a/core/res/res/drawable-hdpi/emo_im_winking.png b/core/res/res/drawable-hdpi/emo_im_winking.png Binary files differindex 6fe1027dea42..b8fd6d9e32bd 100644 --- a/core/res/res/drawable-hdpi/emo_im_winking.png +++ b/core/res/res/drawable-hdpi/emo_im_winking.png diff --git a/core/res/res/drawable-hdpi/emo_im_wtf.png b/core/res/res/drawable-hdpi/emo_im_wtf.png Binary files differindex 1d4a99bfd9e8..b22179523d5a 100644 --- a/core/res/res/drawable-hdpi/emo_im_wtf.png +++ b/core/res/res/drawable-hdpi/emo_im_wtf.png diff --git a/core/res/res/drawable-hdpi/emo_im_yelling.png b/core/res/res/drawable-hdpi/emo_im_yelling.png Binary files differindex 99d694ba7b76..59798cbe0fae 100644 --- a/core/res/res/drawable-hdpi/emo_im_yelling.png +++ b/core/res/res/drawable-hdpi/emo_im_yelling.png diff --git a/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png Binary files differindex 6bb4d1e691d0..73ff79fd9ddb 100644 --- a/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/expander_close_holo_light.9.png b/core/res/res/drawable-hdpi/expander_close_holo_light.9.png Binary files differindex 3fb3eb1bbb47..290c24d77ab4 100644 --- a/core/res/res/drawable-hdpi/expander_close_holo_light.9.png +++ b/core/res/res/drawable-hdpi/expander_close_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png Binary files differindex a679da5b391b..754032eb5bbb 100644 --- a/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/expander_open_holo_light.9.png b/core/res/res/drawable-hdpi/expander_open_holo_light.9.png Binary files differindex 175ce17ffd50..e32c7c74a856 100644 --- a/core/res/res/drawable-hdpi/expander_open_holo_light.9.png +++ b/core/res/res/drawable-hdpi/expander_open_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png Binary files differindex 0a1bca862400..769cb125f4b1 100644 --- a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png Binary files differindex fd5b18d1c3b1..c5372a81f280 100644 --- a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png +++ b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png Binary files differindex 97d61f43c069..1dee51b5c385 100644 --- a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png Binary files differindex 9afd6ab99752..3c1e25adc194 100644 --- a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png +++ b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/fastscroll_track_default_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_track_default_holo_dark.9.png Binary files differindex 5cd1ac7b51ab..707414d059f0 100644 --- a/core/res/res/drawable-hdpi/fastscroll_track_default_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/fastscroll_track_default_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/fastscroll_track_default_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_track_default_holo_light.9.png Binary files differindex 5cd1ac7b51ab..707414d059f0 100644 --- a/core/res/res/drawable-hdpi/fastscroll_track_default_holo_light.9.png +++ b/core/res/res/drawable-hdpi/fastscroll_track_default_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_dark.9.png Binary files differindex 9a7e5aeca66a..4d810dd50823 100644 --- a/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_light.9.png Binary files differindex 9a7e5aeca66a..64fa147a87d4 100644 --- a/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_light.9.png +++ b/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif.png Binary files differindex 1df685865dbd..a89f45f5b970 100644 --- a/core/res/res/drawable-hdpi/ic_audio_ring_notif.png +++ b/core/res/res/drawable-hdpi/ic_audio_ring_notif.png diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute.png Binary files differindex fae02f9a765a..d03badea7849 100644 --- a/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute.png +++ b/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute.png diff --git a/core/res/res/drawable-hdpi/ic_emergency.png b/core/res/res/drawable-hdpi/ic_emergency.png Binary files differindex 89c05e360493..09bcbda5c2e0 100644 --- a/core/res/res/drawable-hdpi/ic_emergency.png +++ b/core/res/res/drawable-hdpi/ic_emergency.png diff --git a/core/res/res/drawable-hdpi/ic_input_delete.png b/core/res/res/drawable-hdpi/ic_input_delete.png Binary files differindex f35f89f69000..5d638bd511ed 100644 --- a/core/res/res/drawable-hdpi/ic_input_delete.png +++ b/core/res/res/drawable-hdpi/ic_input_delete.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_answer_active.png b/core/res/res/drawable-hdpi/ic_lockscreen_answer_active.png Binary files differindex 639529489422..683a57510e91 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_answer_active.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_answer_active.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_answer_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_answer_focused.png Binary files differindex 74fda0f31a14..bdece9fc942f 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_answer_focused.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_answer_focused.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_answer_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_answer_normal.png Binary files differindex 1558a0a9c177..6a8ab241718d 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_answer_normal.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_answer_normal.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png Binary files differindex 620844ec374f..bc718b57b43c 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png Binary files differindex d008afa1ef26..0892c31863b2 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png Binary files differindex e5089003c052..04cc0a23b4aa 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png Binary files differindex 4ffa833b93cf..bb553b1fc2a1 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_decline_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_decline_focused.png Binary files differindex 0ccf36189085..f2fceaabc6d1 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_decline_focused.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_decline_focused.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_decline_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_decline_normal.png Binary files differindex 14a684e93354..e005ffc18c03 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_decline_normal.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_decline_normal.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png Binary files differindex 1b7f499aa7de..f41ad95abb58 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png Binary files differindex 399aa1cdba80..98ab6e919c6a 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_silent_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_silent_focused.png Binary files differindex b79dbbaa2606..651b83709aa4 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_silent_focused.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_silent_focused.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_silent_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_silent_normal.png Binary files differindex 86325458d7a6..babab1d22381 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_silent_normal.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_silent_normal.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_focused.png Binary files differindex e25c7a0db9db..d000866c8502 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_focused.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_focused.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_normal.png Binary files differindex 701fa42b5c3a..82133d02a259 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_normal.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_normal.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_text_focusde.png b/core/res/res/drawable-hdpi/ic_lockscreen_text_focusde.png Binary files differindex c8de3a31995f..26df6b2a87a2 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_text_focusde.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_text_focusde.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png Binary files differindex e3009436ca44..9e36918974d6 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_focused.png Binary files differdeleted file mode 100644 index da7734014a07..000000000000 --- a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_focused.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_normal.png Binary files differindex 7db46c1a8c86..39608932b3e6 100644 --- a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_normal.png +++ b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_normal.png diff --git a/core/res/res/drawable-hdpi/ic_media_embed_play.png b/core/res/res/drawable-hdpi/ic_media_embed_play.png Binary files differindex 23ac7e45e426..05778c181f6f 100644 --- a/core/res/res/drawable-hdpi/ic_media_embed_play.png +++ b/core/res/res/drawable-hdpi/ic_media_embed_play.png diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png Binary files differindex d1e1337f70f4..d37d0a318a4f 100644 --- a/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png Binary files differindex 5d026609b964..0dd8865f4a9a 100644 --- a/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png Binary files differindex bd28a8590ebf..81c52b0b5ea1 100644 --- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png Binary files differindex 037c36256c6c..15500c341ed6 100644 --- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png Binary files differindex 5f2f60433d20..2abc45809c62 100644 --- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png Binary files differindex 7f3459c8688d..bb6aef1d069a 100644 --- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png Binary files differindex e9514b8d7fc4..eb701f241cb9 100644 --- a/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png Binary files differindex b02aa09e7075..886c49317e0b 100644 --- a/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png Binary files differindex b1613613c62b..c2cec7ff1a7f 100644 --- a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png Binary files differindex 0a7b364d65ad..902402e26efd 100644 --- a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_notification_ime_default.png b/core/res/res/drawable-hdpi/ic_notification_ime_default.png Binary files differindex ac598190a0b8..369c88d31707 100644 --- a/core/res/res/drawable-hdpi/ic_notification_ime_default.png +++ b/core/res/res/drawable-hdpi/ic_notification_ime_default.png diff --git a/core/res/res/drawable-hdpi/ic_suggestions_add.png b/core/res/res/drawable-hdpi/ic_suggestions_add.png Binary files differnew file mode 100644 index 000000000000..79c017ac498e --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_suggestions_add.png diff --git a/core/res/res/drawable-hdpi/ic_suggestions_delete.png b/core/res/res/drawable-hdpi/ic_suggestions_delete.png Binary files differnew file mode 100644 index 000000000000..1ae6b96f3683 --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_suggestions_delete.png diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up.png Binary files differdeleted file mode 100644 index 6560696c8edf..000000000000 --- a/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png Binary files differindex 237011c16b44..28b25781b7da 100644 --- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png +++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png Binary files differindex 24180178097d..545cc09c036d 100644 --- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png +++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png Binary files differindex 2120bad70380..9176b3372c4c 100644 --- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png +++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png Binary files differindex 30b3a4d4dc6d..fb34a6deab6c 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png Binary files differindex 0e8ac15b284e..87b2ad67cfea 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png Binary files differindex 762e4b07be7f..1655feacd3c4 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png Binary files differindex 4d3dc683e7fe..61cfe7a24887 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png Binary files differindex fcf3565bee3b..43e2e89fbd77 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png Binary files differindex 12fb9701d9b7..7d80ff6e748f 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png Binary files differindex a82fd1732965..cc21a1c9ff29 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png Binary files differindex a82fd1732965..cc21a1c9ff29 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png Binary files differindex 32845065ab13..3c9c192d8c34 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png Binary files differindex 6afc2d09efd6..6511cd20e4c1 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png Binary files differindex e414e330c004..7b135ea67912 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png Binary files differindex e414e330c004..7b135ea67912 100644 --- a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png Binary files differindex 828c07962271..b6a85a2f66af 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png Binary files differindex e7e22c3862a7..50d979e86143 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png Binary files differindex a2a773b8a467..608dd529f17f 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png Binary files differindex 0b1b1893bf5f..96ff781a213d 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png Binary files differindex ca12894242cf..a48bf2e58c88 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png Binary files differindex 52f8b38d9c59..b69589b21517 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png Binary files differindex 5f9411ab9039..5adfb04fb890 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png Binary files differindex 5f9411ab9039..5adfb04fb890 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png Binary files differindex cdc1775dfb65..ff34463d12db 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png Binary files differindex b4981d45ddb5..0bcfd67e913e 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png Binary files differindex e124a1868b55..00092cc83db6 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png diff --git a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png Binary files differindex e124a1868b55..00092cc83db6 100644 --- a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png +++ b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png diff --git a/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png Binary files differindex 416b456ba425..1b4fed88c462 100644 --- a/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png Binary files differindex ddd242ba8d0c..c8b3177ceabd 100644 --- a/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png +++ b/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/presence_away.png b/core/res/res/drawable-hdpi/presence_away.png Binary files differindex b25b8212eef8..fe5b880f49af 100644 --- a/core/res/res/drawable-hdpi/presence_away.png +++ b/core/res/res/drawable-hdpi/presence_away.png diff --git a/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png Binary files differindex 64eee9345e8d..e3131b115503 100644 --- a/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png Binary files differindex 8817efe997c9..cdc94a135bec 100644 --- a/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png diff --git a/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png Binary files differindex 5a447880c11f..d83522ac67bc 100644 --- a/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png Binary files differindex d47f63a8a25c..2af7814d1aef 100644 --- a/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png diff --git a/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png Binary files differindex 947ac178aac8..e4b766d72456 100644 --- a/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png Binary files differindex 6b2588d55bd3..edd264a37281 100644 --- a/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png diff --git a/core/res/res/drawable-hdpi/rate_star_med_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_med_half_holo_dark.png Binary files differindex 4a02a23cfff1..65f673d762d8 100644 --- a/core/res/res/drawable-hdpi/rate_star_med_half_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_med_half_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png Binary files differindex e73bdcca02a7..3ff3bbd60410 100644 --- a/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png diff --git a/core/res/res/drawable-hdpi/rate_star_med_off_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_med_off_holo_dark.png Binary files differindex e96936c28590..b8bca18154c7 100644 --- a/core/res/res/drawable-hdpi/rate_star_med_off_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_med_off_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png Binary files differindex 76b9c189d0e0..ce9fc2502714 100644 --- a/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png diff --git a/core/res/res/drawable-hdpi/rate_star_med_on_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_med_on_holo_dark.png Binary files differindex cfcf62928c90..1b7fe776ca1d 100644 --- a/core/res/res/drawable-hdpi/rate_star_med_on_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_med_on_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png Binary files differindex a7d5af8a8252..a6fdcff49c2f 100644 --- a/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png diff --git a/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png Binary files differindex 946cdfdc51c0..4fb14f934afd 100644 --- a/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png Binary files differindex d046838760c1..667b8e280789 100644 --- a/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png diff --git a/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png Binary files differindex 6f1ffe874d73..e19cf7aa4e9c 100644 --- a/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png Binary files differindex 6286fcd85afc..8886006d0176 100644 --- a/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png diff --git a/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png Binary files differindex a53b62727e58..bc5d3dba0d12 100644 --- a/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png +++ b/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png diff --git a/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png Binary files differindex dc102a99058a..104100844c75 100644 --- a/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png +++ b/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png diff --git a/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png Binary files differindex e0f55bf2d694..d4b3209e2162 100644 --- a/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png +++ b/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png diff --git a/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png Binary files differindex 7b264f147308..ec7303e12e39 100644 --- a/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png +++ b/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png diff --git a/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png Binary files differindex c3a5f7dc2a5c..19526fee8648 100644 --- a/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png +++ b/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png diff --git a/core/res/res/drawable-hdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-hdpi/scrubber_control_pressed_holo.png Binary files differindex 6fa4e00b90b0..e8f9eefbe00b 100644 --- a/core/res/res/drawable-hdpi/scrubber_control_pressed_holo.png +++ b/core/res/res/drawable-hdpi/scrubber_control_pressed_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png Binary files differindex b59b492576b7..01669381af25 100644 --- a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png +++ b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_16_outer_holo.png b/core/res/res/drawable-hdpi/spinner_16_outer_holo.png Binary files differindex 57b8b31ec6d3..ffdb78af9040 100644 --- a/core/res/res/drawable-hdpi/spinner_16_outer_holo.png +++ b/core/res/res/drawable-hdpi/spinner_16_outer_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png Binary files differindex 14d26a5818d8..ffad7209e470 100644 --- a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png +++ b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png Binary files differindex e457a6685094..f2523f4b0c17 100644 --- a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png +++ b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png Binary files differindex 86c036d7a7d6..f8e3fef633cc 100644 --- a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png +++ b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png Binary files differindex ddd3e74cad87..04c5fb5a26ee 100644 --- a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png +++ b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png Binary files differindex 74e7e2ed2886..a28a6d1607c8 100644 --- a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png +++ b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png Binary files differindex 989a18c0bc36..3d5aa46b7f58 100644 --- a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png +++ b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png Binary files differindex 3128fd9278ce..51a5226b644e 100644 --- a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png Binary files differindex 924a93b7a4e0..a24da9104e03 100644 --- a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png +++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/stat_notify_error.png b/core/res/res/drawable-hdpi/stat_notify_error.png Binary files differindex dbaf94433b45..deb38726301b 100644 --- a/core/res/res/drawable-hdpi/stat_notify_error.png +++ b/core/res/res/drawable-hdpi/stat_notify_error.png diff --git a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png Binary files differindex 716ba9da439c..f3aaa276fc8a 100644 --- a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png +++ b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png diff --git a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png Binary files differindex e65f21a3f54f..e88681261aa3 100644 --- a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png Binary files differindex 76c54841f073..3e92cf0ede3a 100644 --- a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png +++ b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png Binary files differindex 80a7ef1d9bd1..962cefb380fb 100644 --- a/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png Binary files differindex bd11555ae568..e05b345f0e2c 100644 --- a/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png +++ b/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/switch_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_bg_holo_dark.9.png Binary files differindex 1fba7ee14b44..933d99b6796c 100644 --- a/core/res/res/drawable-hdpi/switch_bg_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/switch_bg_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/switch_bg_holo_light.9.png b/core/res/res/drawable-hdpi/switch_bg_holo_light.9.png Binary files differindex 5a484dfc8c68..7abe99a5f544 100644 --- a/core/res/res/drawable-hdpi/switch_bg_holo_light.9.png +++ b/core/res/res/drawable-hdpi/switch_bg_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png Binary files differindex 152c33889d47..0bce7679a709 100644 --- a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png Binary files differindex 9c44d4b77750..3b9c048cbd28 100644 --- a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png +++ b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png Binary files differindex cb456485fac8..a4bd07454f4c 100644 --- a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png Binary files differindex 13dd09aeffb4..587bf4e5c836 100644 --- a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png +++ b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png Binary files differindex e72f42853938..a86be03cad88 100644 --- a/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png Binary files differindex 84504eb4e053..e3b0729e34fc 100644 --- a/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png +++ b/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png Binary files differindex 44a4baa4cc16..4b56420a0a0a 100644 --- a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png Binary files differindex 5c5ee814c304..741674d5218c 100644 --- a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png +++ b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/tab_bottom_holo.9.png b/core/res/res/drawable-hdpi/tab_bottom_holo.9.png Binary files differindex 9286c7a93e8e..8abf2baeb886 100644 --- a/core/res/res/drawable-hdpi/tab_bottom_holo.9.png +++ b/core/res/res/drawable-hdpi/tab_bottom_holo.9.png diff --git a/core/res/res/drawable-hdpi/tab_focus.9.png b/core/res/res/drawable-hdpi/tab_focus.9.png Binary files differindex 89a1c0bcb27c..8862fc72615e 100644 --- a/core/res/res/drawable-hdpi/tab_focus.9.png +++ b/core/res/res/drawable-hdpi/tab_focus.9.png diff --git a/core/res/res/drawable-hdpi/tab_focus_bar_left.9.png b/core/res/res/drawable-hdpi/tab_focus_bar_left.9.png Binary files differindex e879e37808e7..7f40d36703fd 100644 --- a/core/res/res/drawable-hdpi/tab_focus_bar_left.9.png +++ b/core/res/res/drawable-hdpi/tab_focus_bar_left.9.png diff --git a/core/res/res/drawable-hdpi/tab_focus_bar_right.9.png b/core/res/res/drawable-hdpi/tab_focus_bar_right.9.png Binary files differindex e879e37808e7..7f40d36703fd 100644 --- a/core/res/res/drawable-hdpi/tab_focus_bar_right.9.png +++ b/core/res/res/drawable-hdpi/tab_focus_bar_right.9.png diff --git a/core/res/res/drawable-hdpi/tab_press.9.png b/core/res/res/drawable-hdpi/tab_press.9.png Binary files differindex 4c34188426b2..4650d6828453 100644 --- a/core/res/res/drawable-hdpi/tab_press.9.png +++ b/core/res/res/drawable-hdpi/tab_press.9.png diff --git a/core/res/res/drawable-hdpi/tab_press_bar_left.9.png b/core/res/res/drawable-hdpi/tab_press_bar_left.9.png Binary files differindex c5f44f3ece38..b43c592932c0 100644 --- a/core/res/res/drawable-hdpi/tab_press_bar_left.9.png +++ b/core/res/res/drawable-hdpi/tab_press_bar_left.9.png diff --git a/core/res/res/drawable-hdpi/tab_press_bar_right.9.png b/core/res/res/drawable-hdpi/tab_press_bar_right.9.png Binary files differindex c5f44f3ece38..b43c592932c0 100644 --- a/core/res/res/drawable-hdpi/tab_press_bar_right.9.png +++ b/core/res/res/drawable-hdpi/tab_press_bar_right.9.png diff --git a/core/res/res/drawable-hdpi/tab_pressed_holo.9.png b/core/res/res/drawable-hdpi/tab_pressed_holo.9.png Binary files differindex 2adb22ca101e..6d057358eb6e 100644 --- a/core/res/res/drawable-hdpi/tab_pressed_holo.9.png +++ b/core/res/res/drawable-hdpi/tab_pressed_holo.9.png diff --git a/core/res/res/drawable-hdpi/tab_selected.9.png b/core/res/res/drawable-hdpi/tab_selected.9.png Binary files differindex 46a331f5a159..d5d3cee6fc01 100644 --- a/core/res/res/drawable-hdpi/tab_selected.9.png +++ b/core/res/res/drawable-hdpi/tab_selected.9.png diff --git a/core/res/res/drawable-hdpi/tab_selected_bar_left.9.png b/core/res/res/drawable-hdpi/tab_selected_bar_left.9.png Binary files differindex 53efbb4b7d87..c1f950c95355 100644 --- a/core/res/res/drawable-hdpi/tab_selected_bar_left.9.png +++ b/core/res/res/drawable-hdpi/tab_selected_bar_left.9.png diff --git a/core/res/res/drawable-hdpi/tab_selected_bar_right.9.png b/core/res/res/drawable-hdpi/tab_selected_bar_right.9.png Binary files differindex 53efbb4b7d87..c1f950c95355 100644 --- a/core/res/res/drawable-hdpi/tab_selected_bar_right.9.png +++ b/core/res/res/drawable-hdpi/tab_selected_bar_right.9.png diff --git a/core/res/res/drawable-hdpi/tab_unselected.9.png b/core/res/res/drawable-hdpi/tab_unselected.9.png Binary files differindex 74181af4b43c..cdc7a4ad2aa9 100644 --- a/core/res/res/drawable-hdpi/tab_unselected.9.png +++ b/core/res/res/drawable-hdpi/tab_unselected.9.png diff --git a/core/res/res/drawable-hdpi/text_select_handle_left.png b/core/res/res/drawable-hdpi/text_select_handle_left.png Binary files differindex e980857544ef..5adc2e119fd6 100644 --- a/core/res/res/drawable-hdpi/text_select_handle_left.png +++ b/core/res/res/drawable-hdpi/text_select_handle_left.png diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle.png b/core/res/res/drawable-hdpi/text_select_handle_middle.png Binary files differindex 603f497dd4ac..b7a472a76fa9 100644 --- a/core/res/res/drawable-hdpi/text_select_handle_middle.png +++ b/core/res/res/drawable-hdpi/text_select_handle_middle.png diff --git a/core/res/res/drawable-hdpi/text_select_handle_right.png b/core/res/res/drawable-hdpi/text_select_handle_right.png Binary files differindex a5efe304f806..cf94179ef0e3 100644 --- a/core/res/res/drawable-hdpi/text_select_handle_right.png +++ b/core/res/res/drawable-hdpi/text_select_handle_right.png diff --git a/core/res/res/drawable-hdpi/vpn_connected.png b/core/res/res/drawable-hdpi/vpn_connected.png Binary files differindex 65fc6db787bf..c3547e855744 100644 --- a/core/res/res/drawable-hdpi/vpn_connected.png +++ b/core/res/res/drawable-hdpi/vpn_connected.png diff --git a/core/res/res/drawable-hdpi/vpn_disconnected.png b/core/res/res/drawable-hdpi/vpn_disconnected.png Binary files differindex 2440c6909ef5..10a9065cabdd 100644 --- a/core/res/res/drawable-hdpi/vpn_disconnected.png +++ b/core/res/res/drawable-hdpi/vpn_disconnected.png diff --git a/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png Binary files differdeleted file mode 100644 index 0bc86c36a70a..000000000000 --- a/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-ldpi/indicator_code_lock_drag_direction_green_up.png Binary files differdeleted file mode 100644 index 9c8610fce53f..000000000000 --- a/core/res/res/drawable-ldpi/indicator_code_lock_drag_direction_green_up.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png Binary files differindex 5435438399c3..ac83494fff86 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png Binary files differindex b350144ead23..6c247a820a3e 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png Binary files differindex 5010bffac72f..7710165da106 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png Binary files differindex 20f8d3d4951b..15d0c803a4b8 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png Binary files differindex 96a9548ff34c..f1d8aec579bf 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png Binary files differindex 8871519ddd93..0d95a00ffddd 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo.png b/core/res/res/drawable-mdpi/btn_check_on_holo.png Binary files differindex 38ab51ac8c30..2737d8c858e1 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_holo.png +++ b/core/res/res/drawable-mdpi/btn_check_on_holo.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png Binary files differindex 4738e5ab8e8b..4dd94529f9fb 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png Binary files differindex db93b6d01bb9..38abce61f6b8 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png Binary files differindex b47b5dde63e6..b70db89b26a2 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png Binary files differindex ad6947ad8d93..21d54a627786 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_code_lock_default.png b/core/res/res/drawable-mdpi/btn_code_lock_default.png Binary files differindex f524317d33f8..206f9b3bc3b7 100755..100644 --- a/core/res/res/drawable-mdpi/btn_code_lock_default.png +++ b/core/res/res/drawable-mdpi/btn_code_lock_default.png diff --git a/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png Binary files differindex 82fc3b2d331f..4c4adf2cfe34 100644 --- a/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png +++ b/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched.png b/core/res/res/drawable-mdpi/btn_code_lock_touched.png Binary files differindex 5cd436c0b889..98a3b6d5a928 100755..100644 --- a/core/res/res/drawable-mdpi/btn_code_lock_touched.png +++ b/core/res/res/drawable-mdpi/btn_code_lock_touched.png diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png Binary files differindex d1fe1adb6550..ef701ed67d1c 100644 --- a/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png +++ b/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png diff --git a/core/res/res/drawable-mdpi/btn_group_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_focused_holo_dark.9.png Binary files differindex 290b9776963e..db2eae1dff94 100644 --- a/core/res/res/drawable-mdpi/btn_group_focused_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/btn_group_focused_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/btn_group_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_focused_holo_light.9.png Binary files differindex 290b9776963e..db2eae1dff94 100644 --- a/core/res/res/drawable-mdpi/btn_group_focused_holo_light.9.png +++ b/core/res/res/drawable-mdpi/btn_group_focused_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/btn_group_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_pressed_holo_dark.9.png Binary files differindex ffc11b78201e..67b5e4ee757b 100644 --- a/core/res/res/drawable-mdpi/btn_group_pressed_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/btn_group_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/btn_group_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_pressed_holo_light.9.png Binary files differindex 8b5d036ef486..154726710e0a 100644 --- a/core/res/res/drawable-mdpi/btn_group_pressed_holo_light.9.png +++ b/core/res/res/drawable-mdpi/btn_group_pressed_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png Binary files differindex ebea1db0906d..816e14615bde 100644 --- a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png Binary files differindex 761c9361a351..4f4eff2270e8 100644 --- a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png Binary files differindex c505d3d659ea..afaa8ca8d666 100644 --- a/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png Binary files differindex 99a71ef3a03e..b7d90791e841 100644 --- a/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png Binary files differindex 3c48fa10e16f..994eb0c90afb 100644 --- a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_dark.png Binary files differindex c1923e4cb02e..f4a1cbc321ac 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_light.png Binary files differindex 08f4ca7b567e..79ca527b9e43 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_dark.png Binary files differindex 5696511feef3..33d130828d0e 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_light.png Binary files differindex b090127e916c..9672415371c6 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_focused_holo_dark.png Binary files differindex 9f46b757178a..94d3784d5a70 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_off_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_focused_holo_light.png Binary files differindex b4bf9c9bb23c..9f3ce4efcdd1 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_off_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_normal_holo_dark.png Binary files differindex 98c176cfbcb5..05563bffe827 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_normal_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_off_normal_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_normal_holo_light.png Binary files differindex 16708fd40baa..ee166bc09fd2 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_normal_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_off_normal_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_dark.png Binary files differindex 9e946db549e7..4bc4a30bd4f1 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_light.png Binary files differindex 875ec01baebd..dd14aec49268 100644 --- a/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_dark.png Binary files differindex a72fe324d36a..becc09132876 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_light.png Binary files differindex 545899a14014..e49dbab41c42 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_dark.png Binary files differindex aca83b03bf29..61837f842549 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_light.png Binary files differindex 2ff492eb650c..19f139f0c6aa 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_focused_holo_dark.png Binary files differindex 816af011b9c4..9fed6b5a7bfe 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_on_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_focused_holo_light.png Binary files differindex 66ea0c75156d..d52dbb7e57f4 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_on_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_normal_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_normal_holo_dark.png Binary files differindex 3ffc6ca0038d..c0c6b49e7da2 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_normal_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_on_normal_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_normal_holo_light.png Binary files differindex e580075b0eb8..237f7e7dc547 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_normal_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_on_normal_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_dark.png Binary files differindex 20d4ab4232ef..2f1f004001f2 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_dark.png +++ b/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_dark.png diff --git a/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_light.png Binary files differindex b31449576cdd..4bea36bff24a 100644 --- a/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_light.png +++ b/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_light.png diff --git a/core/res/res/drawable-mdpi/emo_im_angel.png b/core/res/res/drawable-mdpi/emo_im_angel.png Binary files differindex 297fcf0f0e50..3efea42df152 100644 --- a/core/res/res/drawable-mdpi/emo_im_angel.png +++ b/core/res/res/drawable-mdpi/emo_im_angel.png diff --git a/core/res/res/drawable-mdpi/emo_im_cool.png b/core/res/res/drawable-mdpi/emo_im_cool.png Binary files differindex 9ee1d5dda643..650ed8f62feb 100644 --- a/core/res/res/drawable-mdpi/emo_im_cool.png +++ b/core/res/res/drawable-mdpi/emo_im_cool.png diff --git a/core/res/res/drawable-mdpi/emo_im_crying.png b/core/res/res/drawable-mdpi/emo_im_crying.png Binary files differindex 42ec8db47d12..ad1e50f585a6 100644 --- a/core/res/res/drawable-mdpi/emo_im_crying.png +++ b/core/res/res/drawable-mdpi/emo_im_crying.png diff --git a/core/res/res/drawable-mdpi/emo_im_embarrassed.png b/core/res/res/drawable-mdpi/emo_im_embarrassed.png Binary files differindex 048f4b1363e0..8a343213f03f 100644 --- a/core/res/res/drawable-mdpi/emo_im_embarrassed.png +++ b/core/res/res/drawable-mdpi/emo_im_embarrassed.png diff --git a/core/res/res/drawable-mdpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-mdpi/emo_im_foot_in_mouth.png Binary files differindex db5c801e4204..9607ff735312 100644 --- a/core/res/res/drawable-mdpi/emo_im_foot_in_mouth.png +++ b/core/res/res/drawable-mdpi/emo_im_foot_in_mouth.png diff --git a/core/res/res/drawable-mdpi/emo_im_happy.png b/core/res/res/drawable-mdpi/emo_im_happy.png Binary files differindex e85af7db84dd..a32472096452 100644 --- a/core/res/res/drawable-mdpi/emo_im_happy.png +++ b/core/res/res/drawable-mdpi/emo_im_happy.png diff --git a/core/res/res/drawable-mdpi/emo_im_kissing.png b/core/res/res/drawable-mdpi/emo_im_kissing.png Binary files differindex 6c2458c57c3b..f18a391b3e2c 100644 --- a/core/res/res/drawable-mdpi/emo_im_kissing.png +++ b/core/res/res/drawable-mdpi/emo_im_kissing.png diff --git a/core/res/res/drawable-mdpi/emo_im_laughing.png b/core/res/res/drawable-mdpi/emo_im_laughing.png Binary files differindex 268c8642eb32..963a4ba68f77 100644 --- a/core/res/res/drawable-mdpi/emo_im_laughing.png +++ b/core/res/res/drawable-mdpi/emo_im_laughing.png diff --git a/core/res/res/drawable-mdpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-mdpi/emo_im_lips_are_sealed.png Binary files differindex a838158cdead..58bd1387aeac 100644 --- a/core/res/res/drawable-mdpi/emo_im_lips_are_sealed.png +++ b/core/res/res/drawable-mdpi/emo_im_lips_are_sealed.png diff --git a/core/res/res/drawable-mdpi/emo_im_money_mouth.png b/core/res/res/drawable-mdpi/emo_im_money_mouth.png Binary files differindex 56fcce4be7f4..718c7e3a63cf 100644 --- a/core/res/res/drawable-mdpi/emo_im_money_mouth.png +++ b/core/res/res/drawable-mdpi/emo_im_money_mouth.png diff --git a/core/res/res/drawable-mdpi/emo_im_sad.png b/core/res/res/drawable-mdpi/emo_im_sad.png Binary files differindex c5245cc6c26c..7daac6c0e39b 100644 --- a/core/res/res/drawable-mdpi/emo_im_sad.png +++ b/core/res/res/drawable-mdpi/emo_im_sad.png diff --git a/core/res/res/drawable-mdpi/emo_im_surprised.png b/core/res/res/drawable-mdpi/emo_im_surprised.png Binary files differindex 231ccb1f606a..b4b614dc55de 100644 --- a/core/res/res/drawable-mdpi/emo_im_surprised.png +++ b/core/res/res/drawable-mdpi/emo_im_surprised.png diff --git a/core/res/res/drawable-mdpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-mdpi/emo_im_tongue_sticking_out.png Binary files differindex 93847189758f..9fa6534c90f7 100644 --- a/core/res/res/drawable-mdpi/emo_im_tongue_sticking_out.png +++ b/core/res/res/drawable-mdpi/emo_im_tongue_sticking_out.png diff --git a/core/res/res/drawable-mdpi/emo_im_undecided.png b/core/res/res/drawable-mdpi/emo_im_undecided.png Binary files differindex 9927af90f9ba..8b2577af738b 100644 --- a/core/res/res/drawable-mdpi/emo_im_undecided.png +++ b/core/res/res/drawable-mdpi/emo_im_undecided.png diff --git a/core/res/res/drawable-mdpi/emo_im_winking.png b/core/res/res/drawable-mdpi/emo_im_winking.png Binary files differindex a9b39bd3aa90..069e9e33f95d 100644 --- a/core/res/res/drawable-mdpi/emo_im_winking.png +++ b/core/res/res/drawable-mdpi/emo_im_winking.png diff --git a/core/res/res/drawable-mdpi/emo_im_wtf.png b/core/res/res/drawable-mdpi/emo_im_wtf.png Binary files differindex 17806523e089..0d963ec826bf 100644 --- a/core/res/res/drawable-mdpi/emo_im_wtf.png +++ b/core/res/res/drawable-mdpi/emo_im_wtf.png diff --git a/core/res/res/drawable-mdpi/emo_im_yelling.png b/core/res/res/drawable-mdpi/emo_im_yelling.png Binary files differindex 18e47153e42f..836f60f68bd2 100644 --- a/core/res/res/drawable-mdpi/emo_im_yelling.png +++ b/core/res/res/drawable-mdpi/emo_im_yelling.png diff --git a/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png Binary files differindex 6fa069fac957..036ffb7bbd98 100644 --- a/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/expander_close_holo_light.9.png b/core/res/res/drawable-mdpi/expander_close_holo_light.9.png Binary files differindex b9067933008e..9f9dd7013c7a 100644 --- a/core/res/res/drawable-mdpi/expander_close_holo_light.9.png +++ b/core/res/res/drawable-mdpi/expander_close_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png Binary files differindex 5c7fa382727c..867f36d1d7d4 100644 --- a/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/expander_open_holo_light.9.png b/core/res/res/drawable-mdpi/expander_open_holo_light.9.png Binary files differindex c392ecbfef4d..7f5ca483c59f 100644 --- a/core/res/res/drawable-mdpi/expander_open_holo_light.9.png +++ b/core/res/res/drawable-mdpi/expander_open_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_dark.9.png Binary files differindex b3fd908915d5..94b944d0705c 100644 --- a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png Binary files differindex a64d4d1a2fb1..987c097065c0 100644 --- a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png +++ b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png Binary files differindex 6469fcaafef6..8d87032affe1 100644 --- a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_light.9.png Binary files differindex fca2e25a78e9..b29042a30276 100644 --- a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_light.9.png +++ b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/fastscroll_track_default_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_track_default_holo_dark.9.png Binary files differindex 55f17c2f5cca..eb2b8bdc2224 100644 --- a/core/res/res/drawable-mdpi/fastscroll_track_default_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/fastscroll_track_default_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/fastscroll_track_default_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_track_default_holo_light.9.png Binary files differindex 55f17c2f5cca..eb2b8bdc2224 100644 --- a/core/res/res/drawable-mdpi/fastscroll_track_default_holo_light.9.png +++ b/core/res/res/drawable-mdpi/fastscroll_track_default_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_dark.9.png Binary files differindex 34e126b26625..6fb59b6f47ca 100644 --- a/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_light.9.png Binary files differindex 34e126b26625..1a63f5dfc316 100644 --- a/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_light.9.png +++ b/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif.png Binary files differindex b9b7c7b79a32..1ce4f52d36dc 100644 --- a/core/res/res/drawable-mdpi/ic_audio_ring_notif.png +++ b/core/res/res/drawable-mdpi/ic_audio_ring_notif.png diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute.png Binary files differindex cbe5021fa6ab..cb17415d4aa3 100644 --- a/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute.png +++ b/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute.png diff --git a/core/res/res/drawable-mdpi/ic_emergency.png b/core/res/res/drawable-mdpi/ic_emergency.png Binary files differindex c6faf1e9e430..dfa17c62f8e9 100755..100644 --- a/core/res/res/drawable-mdpi/ic_emergency.png +++ b/core/res/res/drawable-mdpi/ic_emergency.png diff --git a/core/res/res/drawable-mdpi/ic_input_delete.png b/core/res/res/drawable-mdpi/ic_input_delete.png Binary files differindex ee4c911349aa..47c8708782a2 100644 --- a/core/res/res/drawable-mdpi/ic_input_delete.png +++ b/core/res/res/drawable-mdpi/ic_input_delete.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png Binary files differindex d3cfd17ea104..308fe8a29321 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png Binary files differindex e5ef113b0909..9a2563433d1f 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png Binary files differindex ab723b711e94..77240d03453f 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png Binary files differindex 35aca4e82450..e0b013425e7c 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png Binary files differindex 754d7bc830e5..1d547e118c5b 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-mdpi/ic_lockscreen_unlock_activated.png Binary files differindex 0d3f756cb99a..68409c5b37f9 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_activated.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_unlock_activated.png diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_focused.png b/core/res/res/drawable-mdpi/ic_lockscreen_unlock_focused.png Binary files differdeleted file mode 100644 index 6f51447744a2..000000000000 --- a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_focused.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_unlock_normal.png Binary files differindex dd255f57c7ee..52866f258e32 100644 --- a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_normal.png +++ b/core/res/res/drawable-mdpi/ic_lockscreen_unlock_normal.png diff --git a/core/res/res/drawable-mdpi/ic_media_embed_play.png b/core/res/res/drawable-mdpi/ic_media_embed_play.png Binary files differindex fc5d8c622f6a..3576ce53e421 100644 --- a/core/res/res/drawable-mdpi/ic_media_embed_play.png +++ b/core/res/res/drawable-mdpi/ic_media_embed_play.png diff --git a/core/res/res/drawable-mdpi/ic_media_ff.png b/core/res/res/drawable-mdpi/ic_media_ff.png Binary files differindex 892772eb13e4..170dd2daaa75 100644 --- a/core/res/res/drawable-mdpi/ic_media_ff.png +++ b/core/res/res/drawable-mdpi/ic_media_ff.png diff --git a/core/res/res/drawable-mdpi/ic_media_fullscreen.png b/core/res/res/drawable-mdpi/ic_media_fullscreen.png Binary files differindex 1c60e1586477..960aa851053e 100644 --- a/core/res/res/drawable-mdpi/ic_media_fullscreen.png +++ b/core/res/res/drawable-mdpi/ic_media_fullscreen.png diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png Binary files differindex bbe311b76fda..a6feed0e9e38 100644 --- a/core/res/res/drawable-mdpi/ic_media_next.png +++ b/core/res/res/drawable-mdpi/ic_media_next.png diff --git a/core/res/res/drawable-mdpi/ic_media_pause.png b/core/res/res/drawable-mdpi/ic_media_pause.png Binary files differindex e4e8d86b62a6..548ba0219311 100644 --- a/core/res/res/drawable-mdpi/ic_media_pause.png +++ b/core/res/res/drawable-mdpi/ic_media_pause.png diff --git a/core/res/res/drawable-mdpi/ic_media_play.png b/core/res/res/drawable-mdpi/ic_media_play.png Binary files differindex 8eaf96240ed2..0fe680647e94 100644 --- a/core/res/res/drawable-mdpi/ic_media_play.png +++ b/core/res/res/drawable-mdpi/ic_media_play.png diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png Binary files differindex e9abc7f3bd81..0163d094596d 100644 --- a/core/res/res/drawable-mdpi/ic_media_previous.png +++ b/core/res/res/drawable-mdpi/ic_media_previous.png diff --git a/core/res/res/drawable-mdpi/ic_media_rew.png b/core/res/res/drawable-mdpi/ic_media_rew.png Binary files differindex a5eb94a25460..5489180eb16e 100644 --- a/core/res/res/drawable-mdpi/ic_media_rew.png +++ b/core/res/res/drawable-mdpi/ic_media_rew.png diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png Binary files differindex cb19fea81d73..97e8ac1b775d 100644 --- a/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png Binary files differindex e353d46ffb49..74cb920f487b 100644 --- a/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png Binary files differindex 66a750d6a32b..85f3cb2ad632 100644 --- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png Binary files differindex e7e8c547c728..77f92fb56874 100644 --- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png Binary files differindex 1d2592a9eeaa..ba704b67e3a2 100644 --- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png Binary files differindex 4060afe2362f..01d681697f79 100644 --- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png Binary files differindex 23f3a320c234..093496d4089b 100644 --- a/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png Binary files differindex c9d571cd4ae1..61fd91c8808a 100644 --- a/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_selectall_holo_dark.png Binary files differindex caec299c39f6..da64c7556eba 100644 --- a/core/res/res/drawable-mdpi/ic_menu_selectall_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_selectall_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_selectall_holo_light.png Binary files differindex 434f5d1bcc2d..e0dd67c69445 100644 --- a/core/res/res/drawable-mdpi/ic_menu_selectall_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_selectall_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_notification_ime_default.png b/core/res/res/drawable-mdpi/ic_notification_ime_default.png Binary files differindex 67269e824947..7d97eb575f2a 100644 --- a/core/res/res/drawable-mdpi/ic_notification_ime_default.png +++ b/core/res/res/drawable-mdpi/ic_notification_ime_default.png diff --git a/core/res/res/drawable-mdpi/ic_suggestions_add.png b/core/res/res/drawable-mdpi/ic_suggestions_add.png Binary files differnew file mode 100644 index 000000000000..f91951b6e47c --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_suggestions_add.png diff --git a/core/res/res/drawable-mdpi/ic_suggestions_delete.png b/core/res/res/drawable-mdpi/ic_suggestions_delete.png Binary files differnew file mode 100644 index 000000000000..98eb56538872 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_suggestions_delete.png diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png Binary files differdeleted file mode 100644 index 7ddeba529748..000000000000 --- a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default.png Binary files differindex f6d9f1bf7986..05c194bf63e2 100644 --- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default.png +++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default.png diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png Binary files differindex a627cda96b02..4c4adf2cfe34 100644 --- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png +++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green.png Binary files differindex b7262d17ff1e..8f24832f1149 100644 --- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green.png +++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green.png diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png Binary files differindex 308624bce110..cb5b31a06457 100644 --- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png +++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png Binary files differindex 6c451ec5389a..843474124846 100644 --- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png +++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png Binary files differindex 0329d5855832..1f29da2a25f5 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png Binary files differindex d17ca1c095b6..a27f5aac026f 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png Binary files differindex c41e4b863b24..34268af0076e 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png Binary files differindex 846c2e8af797..304f800edae3 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png Binary files differindex 5543ac6979c1..583542b41f41 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png Binary files differindex 65e7c87fe9ee..d15bd16bc99f 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png Binary files differindex 50a4167f4878..9a5d79f9d9db 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png Binary files differindex 50a4167f4878..9a5d79f9d9db 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png Binary files differindex 025b27e837fb..8051d64610b5 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png Binary files differindex 7dd30e983fde..bcd34e95d6c1 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png Binary files differindex 25c22b6b6daf..cf4bdb6f9bcc 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png Binary files differindex 25c22b6b6daf..cf4bdb6f9bcc 100644 --- a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png Binary files differindex c32596ce3321..0535ff7a8f25 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png Binary files differindex 4b862657640a..360284d48114 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png Binary files differindex e47ff9c3c091..1e0e92c9a296 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png Binary files differindex b5e32d8e1107..14bcce93e556 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png Binary files differindex 543d3e3486b8..6ed2cf01081a 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png Binary files differindex 6b395ddc568d..015a8cf9dc65 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png Binary files differindex f0cd69fb54ec..8bb44f2eead8 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png Binary files differindex f0cd69fb54ec..8bb44f2eead8 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png Binary files differindex bf8136c6950b..6ab5f231d3ed 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png Binary files differindex 2c2bef35c03b..65ec302ac586 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png Binary files differindex 394f063a0272..34d3228b320f 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png Binary files differindex 394f063a0272..34d3228b320f 100644 --- a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png +++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png diff --git a/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png Binary files differindex c64da8d0e712..8c51b013d22c 100644 --- a/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/popup_inline_error.9.png b/core/res/res/drawable-mdpi/popup_inline_error.9.png Binary files differindex 2d62071ad29a..17fbe4a690d9 100644 --- a/core/res/res/drawable-mdpi/popup_inline_error.9.png +++ b/core/res/res/drawable-mdpi/popup_inline_error.9.png diff --git a/core/res/res/drawable-mdpi/popup_inline_error_above.9.png b/core/res/res/drawable-mdpi/popup_inline_error_above.9.png Binary files differindex a318891f258c..1d9381740b44 100644 --- a/core/res/res/drawable-mdpi/popup_inline_error_above.9.png +++ b/core/res/res/drawable-mdpi/popup_inline_error_above.9.png diff --git a/core/res/res/drawable-mdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_big_half_holo_dark.png Binary files differindex 593af6e7c3f7..dac51dfd7882 100644 --- a/core/res/res/drawable-mdpi/rate_star_big_half_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_big_half_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-mdpi/rate_star_big_half_holo_light.png Binary files differindex 3dc3aed1a5e5..441dbf7b7b72 100644 --- a/core/res/res/drawable-mdpi/rate_star_big_half_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_big_half_holo_light.png diff --git a/core/res/res/drawable-mdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_big_off_holo_dark.png Binary files differindex 3650f003c099..cde1fb934fbe 100644 --- a/core/res/res/drawable-mdpi/rate_star_big_off_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_big_off_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-mdpi/rate_star_big_off_holo_light.png Binary files differindex 107e0fb34085..8ecf0f95be02 100644 --- a/core/res/res/drawable-mdpi/rate_star_big_off_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_big_off_holo_light.png diff --git a/core/res/res/drawable-mdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_big_on_holo_dark.png Binary files differindex 2b9d79dfa558..0674db311627 100644 --- a/core/res/res/drawable-mdpi/rate_star_big_on_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_big_on_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-mdpi/rate_star_big_on_holo_light.png Binary files differindex c1196838e299..01179196e5cf 100644 --- a/core/res/res/drawable-mdpi/rate_star_big_on_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_big_on_holo_light.png diff --git a/core/res/res/drawable-mdpi/rate_star_med_half_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_med_half_holo_dark.png Binary files differindex 7dc749db5be7..f2ce7abeea02 100644 --- a/core/res/res/drawable-mdpi/rate_star_med_half_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_med_half_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-mdpi/rate_star_med_half_holo_light.png Binary files differindex 22e2a6692b48..48bcf85518e3 100644 --- a/core/res/res/drawable-mdpi/rate_star_med_half_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_med_half_holo_light.png diff --git a/core/res/res/drawable-mdpi/rate_star_med_off_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_med_off_holo_dark.png Binary files differindex 24adc5bfc298..d2e7ab696fc0 100644 --- a/core/res/res/drawable-mdpi/rate_star_med_off_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_med_off_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-mdpi/rate_star_med_off_holo_light.png Binary files differindex d309d27981ba..69824eb8a87f 100644 --- a/core/res/res/drawable-mdpi/rate_star_med_off_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_med_off_holo_light.png diff --git a/core/res/res/drawable-mdpi/rate_star_med_on_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_med_on_holo_dark.png Binary files differindex af8c4740727c..b3b801675db7 100644 --- a/core/res/res/drawable-mdpi/rate_star_med_on_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_med_on_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-mdpi/rate_star_med_on_holo_light.png Binary files differindex 9f030769eb13..84ca715cebf7 100644 --- a/core/res/res/drawable-mdpi/rate_star_med_on_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_med_on_holo_light.png diff --git a/core/res/res/drawable-mdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_small_half_holo_dark.png Binary files differindex 6b5f41cb5bf5..56a62d2f710c 100644 --- a/core/res/res/drawable-mdpi/rate_star_small_half_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_small_half_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-mdpi/rate_star_small_half_holo_light.png Binary files differindex db84cc71bec3..83b7c1ca8987 100644 --- a/core/res/res/drawable-mdpi/rate_star_small_half_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_small_half_holo_light.png diff --git a/core/res/res/drawable-mdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_small_off_holo_dark.png Binary files differindex 6819f81c7e56..b70244b99b8c 100644 --- a/core/res/res/drawable-mdpi/rate_star_small_off_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_small_off_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-mdpi/rate_star_small_off_holo_light.png Binary files differindex 8b45582a56f9..bb5c08cedf33 100644 --- a/core/res/res/drawable-mdpi/rate_star_small_off_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_small_off_holo_light.png diff --git a/core/res/res/drawable-mdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_small_on_holo_dark.png Binary files differindex 25f6df840b4c..444e88207d6f 100644 --- a/core/res/res/drawable-mdpi/rate_star_small_on_holo_dark.png +++ b/core/res/res/drawable-mdpi/rate_star_small_on_holo_dark.png diff --git a/core/res/res/drawable-mdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-mdpi/rate_star_small_on_holo_light.png Binary files differindex 0d34be92a139..7dba5290d90c 100644 --- a/core/res/res/drawable-mdpi/rate_star_small_on_holo_light.png +++ b/core/res/res/drawable-mdpi/rate_star_small_on_holo_light.png diff --git a/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png Binary files differindex a035f6f44bca..6f58ef0a1cf8 100644 --- a/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png +++ b/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png diff --git a/core/res/res/drawable-mdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-mdpi/scrubber_control_focused_holo.png Binary files differindex 5c9720fb0593..3d8f1347d3c9 100644 --- a/core/res/res/drawable-mdpi/scrubber_control_focused_holo.png +++ b/core/res/res/drawable-mdpi/scrubber_control_focused_holo.png diff --git a/core/res/res/drawable-mdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-mdpi/scrubber_control_normal_holo.png Binary files differindex 2497716c56e9..d480c550cf53 100644 --- a/core/res/res/drawable-mdpi/scrubber_control_normal_holo.png +++ b/core/res/res/drawable-mdpi/scrubber_control_normal_holo.png diff --git a/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png Binary files differindex 5fc3ca23974f..6a414fa006b7 100644 --- a/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png +++ b/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_16_inner_holo.png b/core/res/res/drawable-mdpi/spinner_16_inner_holo.png Binary files differindex c0f1b2052832..eeef0c834acf 100644 --- a/core/res/res/drawable-mdpi/spinner_16_inner_holo.png +++ b/core/res/res/drawable-mdpi/spinner_16_inner_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_16_outer_holo.png b/core/res/res/drawable-mdpi/spinner_16_outer_holo.png Binary files differindex 0492a629ff75..7cc2b54b4894 100644 --- a/core/res/res/drawable-mdpi/spinner_16_outer_holo.png +++ b/core/res/res/drawable-mdpi/spinner_16_outer_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png b/core/res/res/drawable-mdpi/spinner_20_inner_holo.png Binary files differindex 5e141d835f61..4569faedaeba 100644 --- a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png +++ b/core/res/res/drawable-mdpi/spinner_20_inner_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png b/core/res/res/drawable-mdpi/spinner_20_outer_holo.png Binary files differindex 07ba3f38e5d8..9287dd7c87b2 100644 --- a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png +++ b/core/res/res/drawable-mdpi/spinner_20_outer_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_48_inner_holo.png b/core/res/res/drawable-mdpi/spinner_48_inner_holo.png Binary files differindex 8c27069a08c4..9458668f0230 100644 --- a/core/res/res/drawable-mdpi/spinner_48_inner_holo.png +++ b/core/res/res/drawable-mdpi/spinner_48_inner_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_48_outer_holo.png b/core/res/res/drawable-mdpi/spinner_48_outer_holo.png Binary files differindex d5f04903dd3f..4ce73edce72e 100644 --- a/core/res/res/drawable-mdpi/spinner_48_outer_holo.png +++ b/core/res/res/drawable-mdpi/spinner_48_outer_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_76_inner_holo.png b/core/res/res/drawable-mdpi/spinner_76_inner_holo.png Binary files differindex 3e263e83840f..cba1300d3a8f 100644 --- a/core/res/res/drawable-mdpi/spinner_76_inner_holo.png +++ b/core/res/res/drawable-mdpi/spinner_76_inner_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_76_outer_holo.png b/core/res/res/drawable-mdpi/spinner_76_outer_holo.png Binary files differindex 6eb6d10ab7e2..99a5ebbfa69d 100644 --- a/core/res/res/drawable-mdpi/spinner_76_outer_holo.png +++ b/core/res/res/drawable-mdpi/spinner_76_outer_holo.png diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png Binary files differindex dda29986727a..6255e2eb9c61 100644 --- a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png Binary files differindex 951301dfa062..1085248704ab 100644 --- a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png +++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/stat_notify_error.png b/core/res/res/drawable-mdpi/stat_notify_error.png Binary files differindex 168f8f6ff88e..78d59aa1c12c 100644 --- a/core/res/res/drawable-mdpi/stat_notify_error.png +++ b/core/res/res/drawable-mdpi/stat_notify_error.png diff --git a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png Binary files differindex 3bf0d3560156..747cb97a5a36 100644 --- a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png +++ b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png diff --git a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png Binary files differindex b8dd5450a2bc..a161b03a05b3 100644 --- a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png Binary files differindex 11b84265fb5f..c637dd1e55e9 100644 --- a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png +++ b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png Binary files differindex c9481fa4efb1..680d1a06a672 100644 --- a/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png Binary files differindex eb08c872ef74..70da7b343682 100644 --- a/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png +++ b/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/switch_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_bg_holo_dark.9.png Binary files differindex 429d73de7ab0..b5582b553cc9 100644 --- a/core/res/res/drawable-mdpi/switch_bg_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/switch_bg_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/switch_bg_holo_light.9.png b/core/res/res/drawable-mdpi/switch_bg_holo_light.9.png Binary files differindex 693ee3311903..a2af2b5e2001 100644 --- a/core/res/res/drawable-mdpi/switch_bg_holo_light.9.png +++ b/core/res/res/drawable-mdpi/switch_bg_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png Binary files differindex bf4b1617e32e..3d786c01a66a 100644 --- a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png Binary files differindex 45359935bc32..2bad2b8f2df8 100644 --- a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png +++ b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png Binary files differindex c56f49dc78df..f6ed0bf0af0d 100644 --- a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png Binary files differindex 5272f08f4e96..a430b7782f13 100644 --- a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png +++ b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png Binary files differindex 9b7380461fde..6312c599e380 100644 --- a/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png Binary files differindex bcd503f8e80c..208672267053 100644 --- a/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png +++ b/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png Binary files differindex 9c948a5c98b2..e44b1d819b14 100644 --- a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png Binary files differindex b035f427c5a8..ee7e37b06d26 100644 --- a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png +++ b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/tab_selected_v4.9.png b/core/res/res/drawable-mdpi/tab_selected_v4.9.png Binary files differindex 3c1c4ebca4b4..e8e112a5a7e6 100644 --- a/core/res/res/drawable-mdpi/tab_selected_v4.9.png +++ b/core/res/res/drawable-mdpi/tab_selected_v4.9.png diff --git a/core/res/res/drawable-mdpi/tab_unselected_v4.9.png b/core/res/res/drawable-mdpi/tab_unselected_v4.9.png Binary files differindex bb383371a10e..229f5037ae39 100644 --- a/core/res/res/drawable-mdpi/tab_unselected_v4.9.png +++ b/core/res/res/drawable-mdpi/tab_unselected_v4.9.png diff --git a/core/res/res/drawable-mdpi/text_select_handle_left.png b/core/res/res/drawable-mdpi/text_select_handle_left.png Binary files differindex 0c3a0ccfc797..750cdea505da 100644 --- a/core/res/res/drawable-mdpi/text_select_handle_left.png +++ b/core/res/res/drawable-mdpi/text_select_handle_left.png diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle.png b/core/res/res/drawable-mdpi/text_select_handle_middle.png Binary files differindex f488bdd2d924..3cdca907c958 100644 --- a/core/res/res/drawable-mdpi/text_select_handle_middle.png +++ b/core/res/res/drawable-mdpi/text_select_handle_middle.png diff --git a/core/res/res/drawable-mdpi/text_select_handle_right.png b/core/res/res/drawable-mdpi/text_select_handle_right.png Binary files differindex d3880c6ce620..fc3d14497fdb 100644 --- a/core/res/res/drawable-mdpi/text_select_handle_right.png +++ b/core/res/res/drawable-mdpi/text_select_handle_right.png diff --git a/core/res/res/drawable-mdpi/vpn_connected.png b/core/res/res/drawable-mdpi/vpn_connected.png Binary files differindex 0d1a0262154d..7e167f84dfa4 100644 --- a/core/res/res/drawable-mdpi/vpn_connected.png +++ b/core/res/res/drawable-mdpi/vpn_connected.png diff --git a/core/res/res/drawable-mdpi/vpn_disconnected.png b/core/res/res/drawable-mdpi/vpn_disconnected.png Binary files differindex d16d7fbd1db0..a08c42a2702a 100644 --- a/core/res/res/drawable-mdpi/vpn_disconnected.png +++ b/core/res/res/drawable-mdpi/vpn_disconnected.png diff --git a/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_green_up.png Binary files differnew file mode 100644 index 000000000000..cc46f19b19b2 --- /dev/null +++ b/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_green_up.png diff --git a/core/res/res/drawable-nodpi/platlogo.png b/core/res/res/drawable-nodpi/platlogo.png Binary files differindex faabda158a9b..e619ed59bf1e 100644 --- a/core/res/res/drawable-nodpi/platlogo.png +++ b/core/res/res/drawable-nodpi/platlogo.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disable.png b/core/res/res/drawable-xhdpi/btn_check_on_disable.png Binary files differindex 179f191c8e71..11917b5fe54d 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_disable.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_disable.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png Binary files differindex 02e4254d2d7a..041663af8e18 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png Binary files differindex 7e61802c8e3b..ca0dadbfe2a4 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png Binary files differindex cc6326e7e46b..4960b5799501 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png Binary files differindex f468781a07bc..ce1dd23554c4 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png Binary files differindex 1e2536416aaf..0a31fbcdd5d8 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png Binary files differindex fc1af9f8128a..62f6336cce74 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo.png b/core/res/res/drawable-xhdpi/btn_check_on_holo.png Binary files differindex 75f66521e81a..65dd58d7fa58 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_holo.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_holo.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png Binary files differindex c327f56b57c5..dc2379c942af 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png Binary files differindex 74a2ea343a3f..cbb26fd822b3 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed.png Binary files differindex f84a5b040635..995775e67400 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_pressed.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png Binary files differindex 48a6431f3456..9c160affd7dd 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png Binary files differindex 5defddfe322b..eb8521825363 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_check_on_selected.png b/core/res/res/drawable-xhdpi/btn_check_on_selected.png Binary files differindex 963c68ea9e9f..a46f2f4f0266 100644 --- a/core/res/res/drawable-xhdpi/btn_check_on_selected.png +++ b/core/res/res/drawable-xhdpi/btn_check_on_selected.png diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_default.png b/core/res/res/drawable-xhdpi/btn_code_lock_default.png Binary files differindex a644014d58b6..c1358a21ad74 100644 --- a/core/res/res/drawable-xhdpi/btn_code_lock_default.png +++ b/core/res/res/drawable-xhdpi/btn_code_lock_default.png diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png Binary files differindex f6072516b8c8..db1cbe6ca16c 100644 --- a/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png +++ b/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_touched.png b/core/res/res/drawable-xhdpi/btn_code_lock_touched.png Binary files differindex 67faad25eb90..0fafc3ef0436 100644 --- a/core/res/res/drawable-xhdpi/btn_code_lock_touched.png +++ b/core/res/res/drawable-xhdpi/btn_code_lock_touched.png diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png Binary files differindex e057cdd51c59..073c3ac91296 100644 --- a/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png +++ b/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png diff --git a/core/res/res/drawable-xhdpi/btn_default_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_normal.9.png Binary files differindex 4ca0b374b4f0..708090584023 100644 --- a/core/res/res/drawable-xhdpi/btn_default_normal.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_normal.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png Binary files differindex f7af2a477302..704bb554f391 100644 --- a/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png Binary files differindex ab7084ec6b0e..7f64c753f00a 100644 --- a/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed.9.png Binary files differindex 02f5bb82704a..849cd48e62d2 100644 --- a/core/res/res/drawable-xhdpi/btn_default_pressed.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_selected.9.png b/core/res/res/drawable-xhdpi/btn_default_selected.9.png Binary files differindex 0375a18e011e..2be8da670761 100644 --- a/core/res/res/drawable-xhdpi/btn_default_selected.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_selected.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png Binary files differindex d3680731e02c..5b7a3bdb1e5f 100644 --- a/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png Binary files differindex 6d1eb481efbf..36cbd3e5f08d 100644 --- a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png Binary files differindex f4783d4e06c3..3ce0038d3bc8 100644 --- a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png b/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png Binary files differindex 0df43d7d7a09..5874b8c7f14f 100644 --- a/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png diff --git a/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png Binary files differindex 44123463f3f3..fb2fbf5e4431 100644 --- a/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png +++ b/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_disabled_focused.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_disabled_focused.9.png Binary files differindex 0e0e0d15193c..1e4cec3de39a 100644 --- a/core/res/res/drawable-xhdpi/btn_dropdown_disabled_focused.9.png +++ b/core/res/res/drawable-xhdpi/btn_dropdown_disabled_focused.9.png diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_normal.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_normal.9.png Binary files differindex a47ad5a6df5d..aab7658d373f 100644 --- a/core/res/res/drawable-xhdpi/btn_dropdown_normal.9.png +++ b/core/res/res/drawable-xhdpi/btn_dropdown_normal.9.png diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_pressed.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_pressed.9.png Binary files differindex a3851a85e4f1..4a1ddf3fd2f1 100644 --- a/core/res/res/drawable-xhdpi/btn_dropdown_pressed.9.png +++ b/core/res/res/drawable-xhdpi/btn_dropdown_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_selected.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_selected.9.png Binary files differindex 80e4d0410cc1..cdae834e2e0a 100644 --- a/core/res/res/drawable-xhdpi/btn_dropdown_selected.9.png +++ b/core/res/res/drawable-xhdpi/btn_dropdown_selected.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal.9.png Binary files differindex ef9262fca75e..981cad99fcd0 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_off.9.png Binary files differindex 6715afddd4f9..22522931fcb5 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_off.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_off.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_on.9.png Binary files differindex 8ffddcf25dcc..4db7078bfd19 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_on.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_on.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png Binary files differindex 5a52bbc07431..04e7ea127cd6 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_off.9.png Binary files differindex 77c6d7822070..95e91e8fe58e 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_off.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_off.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_on.9.png Binary files differindex ed73f09ab9f7..cdd47d584a53 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_on.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_on.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal.9.png Binary files differindex 08021f99672b..1f3a6b3c08fe 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png Binary files differindex 41c8ccb2954b..2a9b6f49ef05 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png Binary files differindex 546ccbc43b48..096d6e9e9f2a 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png Binary files differindex 802b22eb846b..20852d654b6c 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png Binary files differindex d317f94bd798..271c6b41621f 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png Binary files differindex 80b50a11199f..e72ec794fb74 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_off.9.png Binary files differindex 76202a4dd684..e08dcc508095 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_off.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_off.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_on.9.png Binary files differindex e9b2d7e1bd89..fd512d9cf011 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_on.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_on.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_off.9.png Binary files differindex 8db4f8e20739..b18642d58c85 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_off.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_off.9.png diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_on.9.png Binary files differindex b835a07248ed..134c4a9fe6d1 100644 --- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_on.9.png +++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_on.9.png diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_default.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_default.9.png Binary files differindex 07cb53c08c8a..0a12dc991a88 100644 --- a/core/res/res/drawable-xhdpi/btn_search_dialog_default.9.png +++ b/core/res/res/drawable-xhdpi/btn_search_dialog_default.9.png diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_pressed.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_pressed.9.png Binary files differindex d3ccef89098d..35ad67cf324b 100644 --- a/core/res/res/drawable-xhdpi/btn_search_dialog_pressed.9.png +++ b/core/res/res/drawable-xhdpi/btn_search_dialog_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_selected.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_selected.9.png Binary files differindex c553c58e6501..2f9af47261ea 100644 --- a/core/res/res/drawable-xhdpi/btn_search_dialog_selected.9.png +++ b/core/res/res/drawable-xhdpi/btn_search_dialog_selected.9.png diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_default.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_default.9.png Binary files differindex f478c4694df8..d3c770930d37 100644 --- a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_default.9.png +++ b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_default.9.png diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_pressed.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_pressed.9.png Binary files differindex ea5e50999f14..0c4f0da112c4 100644 --- a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_pressed.9.png +++ b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_selected.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_selected.9.png Binary files differindex a46f0edebc91..2e2f587d08e6 100644 --- a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_selected.9.png +++ b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_selected.9.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off.png b/core/res/res/drawable-xhdpi/btn_star_big_off.png Binary files differindex 4ed5142bbcbb..f60eb48a8778 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_off.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_off.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off_disable.png b/core/res/res/drawable-xhdpi/btn_star_big_off_disable.png Binary files differindex cc52dec15d97..8e0858d512e6 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_off_disable.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_off_disable.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off_disable_focused.png b/core/res/res/drawable-xhdpi/btn_star_big_off_disable_focused.png Binary files differindex fea77171eae5..f77e08c142cb 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_off_disable_focused.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_off_disable_focused.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off_pressed.png b/core/res/res/drawable-xhdpi/btn_star_big_off_pressed.png Binary files differindex 503a5b260425..3f9695ed32df 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_off_pressed.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_off_pressed.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off_selected.png b/core/res/res/drawable-xhdpi/btn_star_big_off_selected.png Binary files differindex 8470723c0725..b2e82da6eb01 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_off_selected.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_off_selected.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on.png b/core/res/res/drawable-xhdpi/btn_star_big_on.png Binary files differindex a094406f091a..7cda08992e47 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_on.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_on.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on_disable.png b/core/res/res/drawable-xhdpi/btn_star_big_on_disable.png Binary files differindex bbf7d170b60e..da50266146da 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_on_disable.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_on_disable.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on_disable_focused.png b/core/res/res/drawable-xhdpi/btn_star_big_on_disable_focused.png Binary files differindex a46ea6942ac5..df07003b12c5 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_on_disable_focused.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_on_disable_focused.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on_pressed.png b/core/res/res/drawable-xhdpi/btn_star_big_on_pressed.png Binary files differindex 7e45f2a733d9..d56f46d027df 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_on_pressed.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_on_pressed.png diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on_selected.png b/core/res/res/drawable-xhdpi/btn_star_big_on_selected.png Binary files differindex 0607b78abb0b..5a62f47a6bce 100644 --- a/core/res/res/drawable-xhdpi/btn_star_big_on_selected.png +++ b/core/res/res/drawable-xhdpi/btn_star_big_on_selected.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_dark.png Binary files differindex 7b479404b58c..f31cf2702dda 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_light.png Binary files differindex 6a819900a74b..9b28db852cb3 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_dark.png Binary files differindex 5f6ff354781f..bec293cc9bdf 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_light.png Binary files differindex 3a0f83de6bff..eec89dfadc5b 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_dark.png Binary files differindex 6fb25b569f28..757908e51311 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_light.png Binary files differindex 44e87c46a254..c58bd5c6b6f7 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png Binary files differindex 01d4a9ae8a48..c591caefa2ae 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_light.png Binary files differindex 967ca90f3eef..b3e981a17cc4 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_dark.png Binary files differindex ebb80ee29e83..85253f7b5317 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_light.png Binary files differindex 9f32c30b4b30..efd26b0ee8f2 100644 --- a/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_dark.png Binary files differindex ffe47dedf2ef..25fd6bb96421 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_light.png Binary files differindex ed3670719ba7..fcd06afb7f19 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_dark.png Binary files differindex fd9da6c67ef8..641f79bf4fc2 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_light.png Binary files differindex f5908dadc685..9e47d8b2ad24 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_dark.png Binary files differindex 7e76adf1f3f2..8f14270a2943 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_light.png Binary files differindex b64a8d55c33d..1d5567020ad9 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png Binary files differindex 48d89f09bb67..032e89f734a4 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_light.png Binary files differindex ae4f9394b211..ef59ce2403a8 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_light.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_dark.png Binary files differindex 4f052cffa28b..e2305cb51c99 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_dark.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_light.png Binary files differindex ea92177b2d82..6643deb2a6c3 100644 --- a/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_light.png +++ b/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_light.png diff --git a/core/res/res/drawable-xhdpi/code_lock_top.9.png b/core/res/res/drawable-xhdpi/code_lock_top.9.png Binary files differindex 6f5cf6261797..31517e4a58b1 100644 --- a/core/res/res/drawable-xhdpi/code_lock_top.9.png +++ b/core/res/res/drawable-xhdpi/code_lock_top.9.png diff --git a/core/res/res/drawable-xhdpi/contact_header_bg.9.png b/core/res/res/drawable-xhdpi/contact_header_bg.9.png Binary files differindex aee15b83ffeb..bde1d5670c04 100644 --- a/core/res/res/drawable-xhdpi/contact_header_bg.9.png +++ b/core/res/res/drawable-xhdpi/contact_header_bg.9.png diff --git a/core/res/res/drawable-xhdpi/divider_vertical_holo_dark.9.png b/core/res/res/drawable-xhdpi/divider_vertical_holo_dark.9.png Binary files differindex 93507893f75b..9666f7355473 100644 --- a/core/res/res/drawable-xhdpi/divider_vertical_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/divider_vertical_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/divider_vertical_holo_light.9.png b/core/res/res/drawable-xhdpi/divider_vertical_holo_light.9.png Binary files differindex e0f6e0adc35e..026017bda180 100644 --- a/core/res/res/drawable-xhdpi/divider_vertical_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/divider_vertical_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/emo_im_angel.png b/core/res/res/drawable-xhdpi/emo_im_angel.png Binary files differindex b4123ffe86c1..8853cbe570fc 100644 --- a/core/res/res/drawable-xhdpi/emo_im_angel.png +++ b/core/res/res/drawable-xhdpi/emo_im_angel.png diff --git a/core/res/res/drawable-xhdpi/emo_im_cool.png b/core/res/res/drawable-xhdpi/emo_im_cool.png Binary files differindex 0efacf895c87..82cbd55d5b5e 100644 --- a/core/res/res/drawable-xhdpi/emo_im_cool.png +++ b/core/res/res/drawable-xhdpi/emo_im_cool.png diff --git a/core/res/res/drawable-xhdpi/emo_im_crying.png b/core/res/res/drawable-xhdpi/emo_im_crying.png Binary files differindex 7de7bf040b50..315112590f08 100644 --- a/core/res/res/drawable-xhdpi/emo_im_crying.png +++ b/core/res/res/drawable-xhdpi/emo_im_crying.png diff --git a/core/res/res/drawable-xhdpi/emo_im_embarrassed.png b/core/res/res/drawable-xhdpi/emo_im_embarrassed.png Binary files differindex baa07653146b..ef2fded97fb7 100644 --- a/core/res/res/drawable-xhdpi/emo_im_embarrassed.png +++ b/core/res/res/drawable-xhdpi/emo_im_embarrassed.png diff --git a/core/res/res/drawable-xhdpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-xhdpi/emo_im_foot_in_mouth.png Binary files differindex afb22bb4382d..c41b19d5b377 100644 --- a/core/res/res/drawable-xhdpi/emo_im_foot_in_mouth.png +++ b/core/res/res/drawable-xhdpi/emo_im_foot_in_mouth.png diff --git a/core/res/res/drawable-xhdpi/emo_im_happy.png b/core/res/res/drawable-xhdpi/emo_im_happy.png Binary files differindex 08a242d2b0fc..a2702b26749a 100644 --- a/core/res/res/drawable-xhdpi/emo_im_happy.png +++ b/core/res/res/drawable-xhdpi/emo_im_happy.png diff --git a/core/res/res/drawable-xhdpi/emo_im_kissing.png b/core/res/res/drawable-xhdpi/emo_im_kissing.png Binary files differindex c643a3cfbfc2..7afd2f69a8ab 100644 --- a/core/res/res/drawable-xhdpi/emo_im_kissing.png +++ b/core/res/res/drawable-xhdpi/emo_im_kissing.png diff --git a/core/res/res/drawable-xhdpi/emo_im_laughing.png b/core/res/res/drawable-xhdpi/emo_im_laughing.png Binary files differindex 0301f808a245..abc3700da6b4 100644 --- a/core/res/res/drawable-xhdpi/emo_im_laughing.png +++ b/core/res/res/drawable-xhdpi/emo_im_laughing.png diff --git a/core/res/res/drawable-xhdpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-xhdpi/emo_im_lips_are_sealed.png Binary files differindex 594e5e7359f5..60592fb85b73 100644 --- a/core/res/res/drawable-xhdpi/emo_im_lips_are_sealed.png +++ b/core/res/res/drawable-xhdpi/emo_im_lips_are_sealed.png diff --git a/core/res/res/drawable-xhdpi/emo_im_money_mouth.png b/core/res/res/drawable-xhdpi/emo_im_money_mouth.png Binary files differindex df9283a7c123..8efcf0b6fa61 100644 --- a/core/res/res/drawable-xhdpi/emo_im_money_mouth.png +++ b/core/res/res/drawable-xhdpi/emo_im_money_mouth.png diff --git a/core/res/res/drawable-xhdpi/emo_im_sad.png b/core/res/res/drawable-xhdpi/emo_im_sad.png Binary files differindex f42f0a91e1a4..81e94b1ec704 100644 --- a/core/res/res/drawable-xhdpi/emo_im_sad.png +++ b/core/res/res/drawable-xhdpi/emo_im_sad.png diff --git a/core/res/res/drawable-xhdpi/emo_im_surprised.png b/core/res/res/drawable-xhdpi/emo_im_surprised.png Binary files differindex 6b057fa2521b..7b7aabf1f1f7 100644 --- a/core/res/res/drawable-xhdpi/emo_im_surprised.png +++ b/core/res/res/drawable-xhdpi/emo_im_surprised.png diff --git a/core/res/res/drawable-xhdpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-xhdpi/emo_im_tongue_sticking_out.png Binary files differindex ef128c551377..1b6a98531ae9 100644 --- a/core/res/res/drawable-xhdpi/emo_im_tongue_sticking_out.png +++ b/core/res/res/drawable-xhdpi/emo_im_tongue_sticking_out.png diff --git a/core/res/res/drawable-xhdpi/emo_im_undecided.png b/core/res/res/drawable-xhdpi/emo_im_undecided.png Binary files differindex fcc0f4276f37..2c2cfa6bbf04 100644 --- a/core/res/res/drawable-xhdpi/emo_im_undecided.png +++ b/core/res/res/drawable-xhdpi/emo_im_undecided.png diff --git a/core/res/res/drawable-xhdpi/emo_im_winking.png b/core/res/res/drawable-xhdpi/emo_im_winking.png Binary files differindex 687b62b4a1fb..6c9cb0e247b2 100644 --- a/core/res/res/drawable-xhdpi/emo_im_winking.png +++ b/core/res/res/drawable-xhdpi/emo_im_winking.png diff --git a/core/res/res/drawable-xhdpi/emo_im_wtf.png b/core/res/res/drawable-xhdpi/emo_im_wtf.png Binary files differindex cb75a18d662e..34861e4093fb 100644 --- a/core/res/res/drawable-xhdpi/emo_im_wtf.png +++ b/core/res/res/drawable-xhdpi/emo_im_wtf.png diff --git a/core/res/res/drawable-xhdpi/emo_im_yelling.png b/core/res/res/drawable-xhdpi/emo_im_yelling.png Binary files differindex 32a7028a705e..0583178a5aaf 100644 --- a/core/res/res/drawable-xhdpi/emo_im_yelling.png +++ b/core/res/res/drawable-xhdpi/emo_im_yelling.png diff --git a/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png Binary files differindex 8005de74ab9c..f56ef3118273 100644 --- a/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png b/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png Binary files differindex 333dd24db2ea..e1570248abf3 100644 --- a/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/expander_ic_maximized.9.png b/core/res/res/drawable-xhdpi/expander_ic_maximized.9.png Binary files differindex 6eed88a1fda7..598b75b59bca 100644 --- a/core/res/res/drawable-xhdpi/expander_ic_maximized.9.png +++ b/core/res/res/drawable-xhdpi/expander_ic_maximized.9.png diff --git a/core/res/res/drawable-xhdpi/expander_ic_minimized.9.png b/core/res/res/drawable-xhdpi/expander_ic_minimized.9.png Binary files differindex 0683be681584..396f41382dcc 100644 --- a/core/res/res/drawable-xhdpi/expander_ic_minimized.9.png +++ b/core/res/res/drawable-xhdpi/expander_ic_minimized.9.png diff --git a/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png Binary files differindex 4a56a80eb3f5..d2e8ae851fe8 100644 --- a/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png b/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png Binary files differindex 67ed4c0a130f..35fb75a442d4 100644 --- a/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png Binary files differindex dfc5e6b6f9a0..6e0244f79eaa 100644 --- a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_light.9.png Binary files differindex eab0cb91ff92..6478a112ebad 100644 --- a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_dark.9.png Binary files differindex e3e0cde4be4e..0330b172e07d 100644 --- a/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_light.9.png Binary files differindex b2bd5ca878c9..57539e450472 100644 --- a/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_dark.9.png Binary files differindex c727bd44627b..751e0d5a85aa 100644 --- a/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_light.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_light.9.png Binary files differindex c727bd44627b..751e0d5a85aa 100644 --- a/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_dark.9.png Binary files differindex f2c6b42031e0..c9427a997b76 100644 --- a/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_light.9.png Binary files differindex f2c6b42031e0..b495fbd7ea1a 100644 --- a/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/frame_gallery_thumb.9.png b/core/res/res/drawable-xhdpi/frame_gallery_thumb.9.png Binary files differindex 915fbed3340b..a6bb25afaf1f 100644 --- a/core/res/res/drawable-xhdpi/frame_gallery_thumb.9.png +++ b/core/res/res/drawable-xhdpi/frame_gallery_thumb.9.png diff --git a/core/res/res/drawable-xhdpi/frame_gallery_thumb_pressed.9.png b/core/res/res/drawable-xhdpi/frame_gallery_thumb_pressed.9.png Binary files differindex 13ea0067944f..85d65faa710f 100644 --- a/core/res/res/drawable-xhdpi/frame_gallery_thumb_pressed.9.png +++ b/core/res/res/drawable-xhdpi/frame_gallery_thumb_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/frame_gallery_thumb_selected.9.png b/core/res/res/drawable-xhdpi/frame_gallery_thumb_selected.9.png Binary files differindex f9471444dd4d..1dadee661704 100644 --- a/core/res/res/drawable-xhdpi/frame_gallery_thumb_selected.9.png +++ b/core/res/res/drawable-xhdpi/frame_gallery_thumb_selected.9.png diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif.png Binary files differindex 3fa419734bf3..0df19342106c 100644 --- a/core/res/res/drawable-xhdpi/ic_audio_ring_notif.png +++ b/core/res/res/drawable-xhdpi/ic_audio_ring_notif.png diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute.png Binary files differindex e8e7fcc4b0ea..85acb93db2b5 100644 --- a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute.png +++ b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute.png diff --git a/core/res/res/drawable-xhdpi/ic_emergency.png b/core/res/res/drawable-xhdpi/ic_emergency.png Binary files differindex f5df6cd1de38..0e975498d5a8 100644 --- a/core/res/res/drawable-xhdpi/ic_emergency.png +++ b/core/res/res/drawable-xhdpi/ic_emergency.png diff --git a/core/res/res/drawable-xhdpi/ic_input_delete.png b/core/res/res/drawable-xhdpi/ic_input_delete.png Binary files differindex 34c5f3939bb7..8b822d9e37c2 100644 --- a/core/res/res/drawable-xhdpi/ic_input_delete.png +++ b/core/res/res/drawable-xhdpi/ic_input_delete.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png Binary files differindex c655d93b0cc7..b8e5733522ef 100644 --- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png Binary files differindex 75173cb701fd..ce5da43fc650 100644 --- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png Binary files differindex 9f6da72fbc13..c16f1431125d 100644 --- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png Binary files differindex 53794fde8cf7..9bed39a3e3e0 100644 --- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png Binary files differindex 544924e4bcf9..b09071b705c2 100644 --- a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_activated.png Binary files differindex 73d7af3cd51b..8a0331d8359d 100644 --- a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_activated.png +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_activated.png diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_focused.png b/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_focused.png Binary files differdeleted file mode 100644 index d067ab8d29fd..000000000000 --- a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_focused.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_normal.png Binary files differindex 1a53c630c5b0..0422117f72d3 100644 --- a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_normal.png +++ b/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_normal.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png Binary files differindex 801434525cb1..ba883aec0ffd 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png Binary files differindex b5359a1963a8..364b1692f3ea 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png Binary files differindex 180365f4e5b7..16632b196392 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png Binary files differindex a31a06f59ce7..6e007c76d2fd 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png Binary files differindex 1ce25e2e419c..a92fb1d4af62 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png Binary files differindex dcd6514a9bf7..930ca8d95e8b 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png Binary files differindex 6e7273f252b9..4c5f7f20d426 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png Binary files differindex b7eedd917afe..6edd4b222ef0 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png Binary files differindex 7125557124de..8eef37dd4698 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png Binary files differindex c7728d4b190a..2e1cf86dbbef 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_notification_ime_default.png b/core/res/res/drawable-xhdpi/ic_notification_ime_default.png Binary files differindex 4d0f074c3910..900801a4d3d7 100644 --- a/core/res/res/drawable-xhdpi/ic_notification_ime_default.png +++ b/core/res/res/drawable-xhdpi/ic_notification_ime_default.png diff --git a/core/res/res/drawable-xhdpi/ic_notification_overlay.9.png b/core/res/res/drawable-xhdpi/ic_notification_overlay.9.png Binary files differindex 010852f86121..a7a8bb3e1dff 100644 --- a/core/res/res/drawable-xhdpi/ic_notification_overlay.9.png +++ b/core/res/res/drawable-xhdpi/ic_notification_overlay.9.png diff --git a/core/res/res/drawable-xhdpi/ic_suggestions_add.png b/core/res/res/drawable-xhdpi/ic_suggestions_add.png Binary files differnew file mode 100644 index 000000000000..aac038cbed27 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_suggestions_add.png diff --git a/core/res/res/drawable-xhdpi/ic_suggestions_delete.png b/core/res/res/drawable-xhdpi/ic_suggestions_delete.png Binary files differnew file mode 100644 index 000000000000..077e9fcbec95 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_suggestions_delete.png diff --git a/core/res/res/drawable-xhdpi/icon_highlight_rectangle.9.png b/core/res/res/drawable-xhdpi/icon_highlight_rectangle.9.png Binary files differindex b26180dfa075..cdc37f1e23dc 100644 --- a/core/res/res/drawable-xhdpi/icon_highlight_rectangle.9.png +++ b/core/res/res/drawable-xhdpi/icon_highlight_rectangle.9.png diff --git a/core/res/res/drawable-xhdpi/icon_highlight_square.9.png b/core/res/res/drawable-xhdpi/icon_highlight_square.9.png Binary files differindex f45f1c51794e..cc2ab8c0ff96 100644 --- a/core/res/res/drawable-xhdpi/icon_highlight_square.9.png +++ b/core/res/res/drawable-xhdpi/icon_highlight_square.9.png diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_green_up.png Binary files differdeleted file mode 100644 index a89b8d5d5609..000000000000 --- a/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_green_up.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default.png Binary files differindex 997d6a5eec08..0812cb58107f 100644 --- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default.png +++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default.png diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png Binary files differindex d98a126327c2..db1cbe6ca16c 100644 --- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png +++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green.png Binary files differindex 2eb69f676109..3ab2e99785c3 100644 --- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green.png +++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green.png diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png Binary files differindex 4491f02f9b5f..de4ca916ca58 100644 --- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png +++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png Binary files differindex 6e91fbcdf62a..853b0f0ced00 100644 --- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png +++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png diff --git a/core/res/res/drawable-xhdpi/list_section_header_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_section_header_holo_dark.9.png Binary files differindex 4412331cd5e4..6cb42c1b5bca 100644 --- a/core/res/res/drawable-xhdpi/list_section_header_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/list_section_header_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/list_section_header_holo_light.9.png b/core/res/res/drawable-xhdpi/list_section_header_holo_light.9.png Binary files differindex d0cba8d761a0..f646a4135bd0 100644 --- a/core/res/res/drawable-xhdpi/list_section_header_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/list_section_header_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/menu_background.9.png b/core/res/res/drawable-xhdpi/menu_background.9.png Binary files differindex b784f711c9b9..3aa8ccbfd5cb 100644 --- a/core/res/res/drawable-xhdpi/menu_background.9.png +++ b/core/res/res/drawable-xhdpi/menu_background.9.png diff --git a/core/res/res/drawable-xhdpi/menu_background_fill_parent_width.9.png b/core/res/res/drawable-xhdpi/menu_background_fill_parent_width.9.png Binary files differindex ab43013078e7..af08de2e16a1 100644 --- a/core/res/res/drawable-xhdpi/menu_background_fill_parent_width.9.png +++ b/core/res/res/drawable-xhdpi/menu_background_fill_parent_width.9.png diff --git a/core/res/res/drawable-xhdpi/menu_separator.9.png b/core/res/res/drawable-xhdpi/menu_separator.9.png Binary files differindex 3251f9587a50..3c3722cbc72f 100644 --- a/core/res/res/drawable-xhdpi/menu_separator.9.png +++ b/core/res/res/drawable-xhdpi/menu_separator.9.png diff --git a/core/res/res/drawable-xhdpi/menu_submenu_background.9.png b/core/res/res/drawable-xhdpi/menu_submenu_background.9.png Binary files differindex 54b2be68553a..4a8b2ad873d2 100644 --- a/core/res/res/drawable-xhdpi/menu_submenu_background.9.png +++ b/core/res/res/drawable-xhdpi/menu_submenu_background.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png Binary files differindex b8220ceb7ec4..62b267e6159d 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png Binary files differindex 7f4f0937419c..5f38c35c1faf 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_dark.png Binary files differindex beae86df3cfe..1c2f33e14803 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_light.png Binary files differindex 1f5b745be6fd..4e688bcd1abc 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_dark.png Binary files differindex cee62f8d6873..dc422f2f95b3 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_light.png Binary files differindex 367dad4b66ba..afc02db78ce1 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_dark.png Binary files differindex 66b4807f338a..3604013f00e4 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_light.png Binary files differindex b99572cad02d..a16cd38ec2be 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_dark.png Binary files differindex 37cd3ce74d39..b975b6398696 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_light.png Binary files differindex 37cd3ce74d39..b975b6398696 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_longpressed_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png Binary files differindex c10b671f16d3..b1d3e7b3f9de 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_dark.png Binary files differindex 18e7c8e18709..39cdb93f8854 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_light.png Binary files differindex 5ddece8f9633..2a14ac559895 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_normal_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png Binary files differindex bfae684ddfd3..e61c469afd12 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_dark.png Binary files differindex 7459f478fa5b..4827377c244a 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_light.png Binary files differindex 7459f478fa5b..4827377c244a 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_pressed_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png Binary files differindex 945163094d69..ed0c0160b73e 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png Binary files differindex 01cc01a98987..279087c4c868 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png Binary files differindex b4d9c7f33102..1b3467acf57e 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png Binary files differindex 5f3d98225eff..930415e7a4f3 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png Binary files differindex 434f05fbbab3..5240d0874c9c 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png Binary files differindex 0c329945d58e..4b7911279146 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png Binary files differindex cba1e76cb088..6c2f397175cd 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_dark.png Binary files differindex b13f8e8d0715..97ea0b5fe4b3 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_light.png Binary files differindex b71cc03081ac..e59e2a7e18b7 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_dark.png Binary files differindex 982f6255d87a..3b8fa7fda9fa 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_light.png Binary files differindex fd3fa74afa1a..77a1dd4cb885 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_dark.png Binary files differindex 57dcf2785a6b..24c2d8445fa8 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_light.png Binary files differindex eff8c2204b73..b2566dc3e486 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_dark.png Binary files differindex 15bed2c60f7b..7075af79495a 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_light.png Binary files differindex 15bed2c60f7b..7075af79495a 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_longpressed_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png Binary files differindex ee270b44aea3..699a9f5f7556 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_dark.png Binary files differindex 74bc6dfbda75..11b60a96e043 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_light.png Binary files differindex 8fe215974c85..074fae59b4cb 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_normal_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png Binary files differindex 297f77c768a6..5504fee0ea3a 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_dark.png Binary files differindex 97cdcb13f115..2310f830ecf0 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_dark.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_light.png Binary files differindex 97cdcb13f115..2310f830ecf0 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_light.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_pressed_holo_light.png diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png Binary files differindex e5d512699c33..585cf304efc6 100644 --- a/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png +++ b/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png diff --git a/core/res/res/drawable-xhdpi/panel_background.9.png b/core/res/res/drawable-xhdpi/panel_background.9.png Binary files differindex 2ceae602f6b0..f3a3a9d9c6bd 100644 --- a/core/res/res/drawable-xhdpi/panel_background.9.png +++ b/core/res/res/drawable-xhdpi/panel_background.9.png diff --git a/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png Binary files differindex c171b7c7bc03..9bdf3f1665c7 100644 --- a/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/password_field_default.9.png b/core/res/res/drawable-xhdpi/password_field_default.9.png Binary files differindex cf8329e3862d..9aa677695ea8 100644 --- a/core/res/res/drawable-xhdpi/password_field_default.9.png +++ b/core/res/res/drawable-xhdpi/password_field_default.9.png diff --git a/core/res/res/drawable-xhdpi/password_keyboard_background_holo.9.png b/core/res/res/drawable-xhdpi/password_keyboard_background_holo.9.png Binary files differindex 65ea61bc7869..7f951300667e 100644 --- a/core/res/res/drawable-xhdpi/password_keyboard_background_holo.9.png +++ b/core/res/res/drawable-xhdpi/password_keyboard_background_holo.9.png diff --git a/core/res/res/drawable-xhdpi/popup_center_bright.9.png b/core/res/res/drawable-xhdpi/popup_center_bright.9.png Binary files differindex b1a8e3e182a1..97614e396a98 100644 --- a/core/res/res/drawable-xhdpi/popup_center_bright.9.png +++ b/core/res/res/drawable-xhdpi/popup_center_bright.9.png diff --git a/core/res/res/drawable-xhdpi/popup_full_bright.9.png b/core/res/res/drawable-xhdpi/popup_full_bright.9.png Binary files differindex 114faa0e1b8c..f10dd85af9cb 100644 --- a/core/res/res/drawable-xhdpi/popup_full_bright.9.png +++ b/core/res/res/drawable-xhdpi/popup_full_bright.9.png diff --git a/core/res/res/drawable-xhdpi/popup_full_dark.9.png b/core/res/res/drawable-xhdpi/popup_full_dark.9.png Binary files differindex 996beaa6e94b..7de3e9d8c793 100644 --- a/core/res/res/drawable-xhdpi/popup_full_dark.9.png +++ b/core/res/res/drawable-xhdpi/popup_full_dark.9.png diff --git a/core/res/res/drawable-xhdpi/popup_inline_error.9.png b/core/res/res/drawable-xhdpi/popup_inline_error.9.png Binary files differindex 2784c3066ff9..a24e607821f7 100644 --- a/core/res/res/drawable-xhdpi/popup_inline_error.9.png +++ b/core/res/res/drawable-xhdpi/popup_inline_error.9.png diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_above.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_above.9.png Binary files differindex f26be8c70711..e382712de9e2 100644 --- a/core/res/res/drawable-xhdpi/popup_inline_error_above.9.png +++ b/core/res/res/drawable-xhdpi/popup_inline_error_above.9.png diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_dark.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_dark.9.png Binary files differindex 622095bfca75..3f23144632c6 100644 --- a/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png Binary files differindex bf8cf4c5870e..41848dd92978 100644 --- a/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_dark.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_dark.9.png Binary files differindex 3e155decb26d..b2a1d8c230cf 100644 --- a/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png Binary files differindex 1c1974ab4cf0..27218f2cf833 100644 --- a/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_dark.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_dark.9.png Binary files differindex 52d95afa8dab..49d1ed5c305e 100644 --- a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png Binary files differindex 2613e0d954d2..8be8ac80f283 100644 --- a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_right_holo_dark.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_right_holo_dark.9.png Binary files differindex b7986e7c4681..3f9e4aabfb5f 100644 --- a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_right_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_right_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png Binary files differindex e964b39467bb..46f3640c1a54 100644 --- a/core/res/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_half.png b/core/res/res/drawable-xhdpi/rate_star_big_half.png Binary files differindex 68c77a879467..2ecb3b5e1f91 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_half.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_half.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_big_half_holo_dark.png Binary files differindex 637c727fa6fc..f9d3cecc7d69 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_half_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_half_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_big_half_holo_light.png Binary files differindex 50f06ddf30ed..bbdc70d320ca 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_half_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_half_holo_light.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_off.png b/core/res/res/drawable-xhdpi/rate_star_big_off.png Binary files differindex 2389fff3af6a..8dae7140c003 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_off.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_off.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_big_off_holo_dark.png Binary files differindex 96c96fbce424..34b94dbcb3fb 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_off_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_off_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_big_off_holo_light.png Binary files differindex 9e8cd54f9ab2..34cb926b024d 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_off_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_off_holo_light.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_on.png b/core/res/res/drawable-xhdpi/rate_star_big_on.png Binary files differindex 39467dd052f9..43633e15ccac 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_on.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_on.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_big_on_holo_dark.png Binary files differindex 1e42698a2f26..273fd16da5e9 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_on_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_on_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_big_on_holo_light.png Binary files differindex 538e1a835d69..dbd11bd68636 100644 --- a/core/res/res/drawable-xhdpi/rate_star_big_on_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_big_on_holo_light.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_half.png b/core/res/res/drawable-xhdpi/rate_star_med_half.png Binary files differindex 6c6011428122..44178c9ab3aa 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_half.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_half.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_half_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_med_half_holo_dark.png Binary files differindex c35d9a4986a6..013543e004f6 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_half_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_half_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_med_half_holo_light.png Binary files differindex f74ea469f573..801703f29494 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_half_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_half_holo_light.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_off.png b/core/res/res/drawable-xhdpi/rate_star_med_off.png Binary files differindex 3428a3b63d3e..101692d4017f 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_off.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_off.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_off_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_med_off_holo_dark.png Binary files differindex be309705d625..d411e25ea5a3 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_off_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_off_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_med_off_holo_light.png Binary files differindex 1d19a88e0e81..39f0fa2e8297 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_off_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_off_holo_light.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_on.png b/core/res/res/drawable-xhdpi/rate_star_med_on.png Binary files differindex 0acddec3b15d..a650d0d08d94 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_on.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_on.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_on_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_med_on_holo_dark.png Binary files differindex d9122b4adefe..fdfe9322a88e 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_on_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_on_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_med_on_holo_light.png Binary files differindex 106ae7791f74..ca88d284623f 100644 --- a/core/res/res/drawable-xhdpi/rate_star_med_on_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_med_on_holo_light.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_half.png b/core/res/res/drawable-xhdpi/rate_star_small_half.png Binary files differindex b7a5709617fc..a7e97a58e636 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_half.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_half.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_small_half_holo_dark.png Binary files differindex fc09cd697d7e..3d2a77404a2e 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_half_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_half_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_small_half_holo_light.png Binary files differindex 663332f6f96d..9221829f7526 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_half_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_half_holo_light.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_off.png b/core/res/res/drawable-xhdpi/rate_star_small_off.png Binary files differindex 2516cccc7a75..71140ac81e5d 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_off.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_off.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_small_off_holo_dark.png Binary files differindex 8fc525fc13d1..346daa31fd46 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_off_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_off_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_small_off_holo_light.png Binary files differindex 59b50605fcce..4c2b62c3f76d 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_off_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_off_holo_light.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_on.png b/core/res/res/drawable-xhdpi/rate_star_small_on.png Binary files differindex 327fd1ffa7fa..ddfb876d25e9 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_on.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_on.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_small_on_holo_dark.png Binary files differindex 09bb66b083a0..9bf24666dea9 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_on_holo_dark.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_on_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_small_on_holo_light.png Binary files differindex b1ee6eb17c84..187eeded5e50 100644 --- a/core/res/res/drawable-xhdpi/rate_star_small_on_holo_light.png +++ b/core/res/res/drawable-xhdpi/rate_star_small_on_holo_light.png diff --git a/core/res/res/drawable-xhdpi/scrollbar_handle_accelerated_anim2.9.png b/core/res/res/drawable-xhdpi/scrollbar_handle_accelerated_anim2.9.png Binary files differindex fdbf4dd925f0..3cf84a5a8d19 100644 --- a/core/res/res/drawable-xhdpi/scrollbar_handle_accelerated_anim2.9.png +++ b/core/res/res/drawable-xhdpi/scrollbar_handle_accelerated_anim2.9.png diff --git a/core/res/res/drawable-xhdpi/scrollbar_handle_vertical.9.png b/core/res/res/drawable-xhdpi/scrollbar_handle_vertical.9.png Binary files differindex 4f6391f53613..24789a5c2a1f 100644 --- a/core/res/res/drawable-xhdpi/scrollbar_handle_vertical.9.png +++ b/core/res/res/drawable-xhdpi/scrollbar_handle_vertical.9.png diff --git a/core/res/res/drawable-xhdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-xhdpi/scrubber_control_disabled_holo.png Binary files differindex d70151af4142..4715cfb7cb36 100644 --- a/core/res/res/drawable-xhdpi/scrubber_control_disabled_holo.png +++ b/core/res/res/drawable-xhdpi/scrubber_control_disabled_holo.png diff --git a/core/res/res/drawable-xhdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-xhdpi/scrubber_control_focused_holo.png Binary files differindex 017688fb124d..d41d5a38678e 100644 --- a/core/res/res/drawable-xhdpi/scrubber_control_focused_holo.png +++ b/core/res/res/drawable-xhdpi/scrubber_control_focused_holo.png diff --git a/core/res/res/drawable-xhdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-xhdpi/scrubber_control_normal_holo.png Binary files differindex 727fcf1af8dd..4f0e06dd710c 100644 --- a/core/res/res/drawable-xhdpi/scrubber_control_normal_holo.png +++ b/core/res/res/drawable-xhdpi/scrubber_control_normal_holo.png diff --git a/core/res/res/drawable-xhdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-xhdpi/scrubber_control_pressed_holo.png Binary files differindex 6d03e42ff043..5d9f860e636a 100644 --- a/core/res/res/drawable-xhdpi/scrubber_control_pressed_holo.png +++ b/core/res/res/drawable-xhdpi/scrubber_control_pressed_holo.png diff --git a/core/res/res/drawable-xhdpi/search_plate.9.png b/core/res/res/drawable-xhdpi/search_plate.9.png Binary files differindex 2ad7615df04b..f917cb66ce02 100644 --- a/core/res/res/drawable-xhdpi/search_plate.9.png +++ b/core/res/res/drawable-xhdpi/search_plate.9.png diff --git a/core/res/res/drawable-xhdpi/settings_header_raw.9.png b/core/res/res/drawable-xhdpi/settings_header_raw.9.png Binary files differindex 41e6c31a8371..c248237858ba 100644 --- a/core/res/res/drawable-xhdpi/settings_header_raw.9.png +++ b/core/res/res/drawable-xhdpi/settings_header_raw.9.png diff --git a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png Binary files differindex 7294519fd012..9afd52fae827 100644 --- a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png +++ b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png diff --git a/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png Binary files differindex d43da4e14e5f..afd4bb921f57 100644 --- a/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png +++ b/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png diff --git a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png Binary files differindex eecac27d655c..76e9428beb16 100644 --- a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png +++ b/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png diff --git a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png Binary files differindex eb91b2c729fe..6f693d631535 100644 --- a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png +++ b/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png diff --git a/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png Binary files differindex b1b8232e5cbc..19517c4b0aee 100644 --- a/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png +++ b/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png diff --git a/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png Binary files differindex 0c15e128690f..14143c51c351 100644 --- a/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png +++ b/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png diff --git a/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png Binary files differindex 6215e95aa2d4..4c92e956fe8c 100644 --- a/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png +++ b/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png diff --git a/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png Binary files differindex 0a67fff8efb2..fe1d615a2ddc 100644 --- a/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png +++ b/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png Binary files differindex 9ee1f8ceb778..5253673642fb 100644 --- a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png Binary files differindex e3e8656c3afe..cfb4a9cb4c16 100644 --- a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/spinner_dropdown_background_down.9.png b/core/res/res/drawable-xhdpi/spinner_dropdown_background_down.9.png Binary files differindex b4352186ff81..7814354d1cd9 100644 --- a/core/res/res/drawable-xhdpi/spinner_dropdown_background_down.9.png +++ b/core/res/res/drawable-xhdpi/spinner_dropdown_background_down.9.png diff --git a/core/res/res/drawable-xhdpi/spinner_dropdown_background_up.9.png b/core/res/res/drawable-xhdpi/spinner_dropdown_background_up.9.png Binary files differindex a45c7617715c..17ee05c6c5bc 100644 --- a/core/res/res/drawable-xhdpi/spinner_dropdown_background_up.9.png +++ b/core/res/res/drawable-xhdpi/spinner_dropdown_background_up.9.png diff --git a/core/res/res/drawable-xhdpi/spinner_normal.9.png b/core/res/res/drawable-xhdpi/spinner_normal.9.png Binary files differindex 71b65ddca777..1ecf8978acc6 100644 --- a/core/res/res/drawable-xhdpi/spinner_normal.9.png +++ b/core/res/res/drawable-xhdpi/spinner_normal.9.png diff --git a/core/res/res/drawable-xhdpi/spinner_press.9.png b/core/res/res/drawable-xhdpi/spinner_press.9.png Binary files differindex d7233baa19ad..87af85cf46c3 100644 --- a/core/res/res/drawable-xhdpi/spinner_press.9.png +++ b/core/res/res/drawable-xhdpi/spinner_press.9.png diff --git a/core/res/res/drawable-xhdpi/spinner_select.9.png b/core/res/res/drawable-xhdpi/spinner_select.9.png Binary files differindex a1b11e0b12ac..15b7a902f65b 100644 --- a/core/res/res/drawable-xhdpi/spinner_select.9.png +++ b/core/res/res/drawable-xhdpi/spinner_select.9.png diff --git a/core/res/res/drawable-xhdpi/stat_notify_error.png b/core/res/res/drawable-xhdpi/stat_notify_error.png Binary files differindex c7ac11ff7fa2..2d0283e7e8d7 100644 --- a/core/res/res/drawable-xhdpi/stat_notify_error.png +++ b/core/res/res/drawable-xhdpi/stat_notify_error.png diff --git a/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png Binary files differindex 1909183366fd..6bb7512cbf82 100644 --- a/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png +++ b/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png diff --git a/core/res/res/drawable-xhdpi/status_bar_header_background.9.png b/core/res/res/drawable-xhdpi/status_bar_header_background.9.png Binary files differindex d03720f81ae7..efd3e97e35d0 100644 --- a/core/res/res/drawable-xhdpi/status_bar_header_background.9.png +++ b/core/res/res/drawable-xhdpi/status_bar_header_background.9.png diff --git a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png Binary files differindex cf10fb92da83..ea53b5f3f1b4 100644 --- a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png Binary files differindex fe7a441e83fe..8a4b61aa89ec 100644 --- a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png Binary files differindex 54ae97993197..6a280dc6cd14 100644 --- a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png Binary files differindex 305cc356a23c..34a93041ac0f 100644 --- a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png Binary files differindex 05dfedeaec58..757fdd4ff02e 100644 --- a/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png Binary files differindex 63bbc4166e8b..8873ccca1cec 100644 --- a/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png Binary files differindex d830a99af538..d22226ed6c75 100644 --- a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png +++ b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png diff --git a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png Binary files differindex 17802601e8de..c94248c01b1a 100644 --- a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png +++ b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png diff --git a/core/res/res/drawable-xhdpi/tab_selected_v4.9.png b/core/res/res/drawable-xhdpi/tab_selected_v4.9.png Binary files differindex e867f90df55b..f1f4ec6a96de 100644 --- a/core/res/res/drawable-xhdpi/tab_selected_v4.9.png +++ b/core/res/res/drawable-xhdpi/tab_selected_v4.9.png diff --git a/core/res/res/drawable-xhdpi/tab_unselected_v4.9.png b/core/res/res/drawable-xhdpi/tab_unselected_v4.9.png Binary files differindex 60b980737cce..1df8c3a0b784 100644 --- a/core/res/res/drawable-xhdpi/tab_unselected_v4.9.png +++ b/core/res/res/drawable-xhdpi/tab_unselected_v4.9.png diff --git a/core/res/res/drawable-xhdpi/text_select_handle_left.png b/core/res/res/drawable-xhdpi/text_select_handle_left.png Binary files differindex 5fcbc528ff11..98d10c92928b 100644 --- a/core/res/res/drawable-xhdpi/text_select_handle_left.png +++ b/core/res/res/drawable-xhdpi/text_select_handle_left.png diff --git a/core/res/res/drawable-xhdpi/text_select_handle_middle.png b/core/res/res/drawable-xhdpi/text_select_handle_middle.png Binary files differindex 05c2ca71a2a5..058b30b731bc 100644 --- a/core/res/res/drawable-xhdpi/text_select_handle_middle.png +++ b/core/res/res/drawable-xhdpi/text_select_handle_middle.png diff --git a/core/res/res/drawable-xhdpi/text_select_handle_right.png b/core/res/res/drawable-xhdpi/text_select_handle_right.png Binary files differindex ebf97c40c2a3..b3a0c9f47ec3 100644 --- a/core/res/res/drawable-xhdpi/text_select_handle_right.png +++ b/core/res/res/drawable-xhdpi/text_select_handle_right.png diff --git a/core/res/res/drawable-xhdpi/textfield_default.9.png b/core/res/res/drawable-xhdpi/textfield_default.9.png Binary files differindex 20b1a098451a..f084f47dfc41 100644 --- a/core/res/res/drawable-xhdpi/textfield_default.9.png +++ b/core/res/res/drawable-xhdpi/textfield_default.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_disabled.9.png b/core/res/res/drawable-xhdpi/textfield_disabled.9.png Binary files differindex 794dce806376..1940051f7acd 100644 --- a/core/res/res/drawable-xhdpi/textfield_disabled.9.png +++ b/core/res/res/drawable-xhdpi/textfield_disabled.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_selected.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_selected.9.png Binary files differindex b708d8241894..335bee64b4ec 100644 --- a/core/res/res/drawable-xhdpi/textfield_disabled_selected.9.png +++ b/core/res/res/drawable-xhdpi/textfield_disabled_selected.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_search_default.9.png b/core/res/res/drawable-xhdpi/textfield_search_default.9.png Binary files differindex 0ed71f7e0022..ad4b935c69f5 100644 --- a/core/res/res/drawable-xhdpi/textfield_search_default.9.png +++ b/core/res/res/drawable-xhdpi/textfield_search_default.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_search_empty_default.9.png b/core/res/res/drawable-xhdpi/textfield_search_empty_default.9.png Binary files differindex 290dd38cc515..0c60f9edccea 100644 --- a/core/res/res/drawable-xhdpi/textfield_search_empty_default.9.png +++ b/core/res/res/drawable-xhdpi/textfield_search_empty_default.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_search_empty_pressed.9.png b/core/res/res/drawable-xhdpi/textfield_search_empty_pressed.9.png Binary files differindex bf20153b7bbd..741bed9731c1 100644 --- a/core/res/res/drawable-xhdpi/textfield_search_empty_pressed.9.png +++ b/core/res/res/drawable-xhdpi/textfield_search_empty_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_search_empty_selected.9.png b/core/res/res/drawable-xhdpi/textfield_search_empty_selected.9.png Binary files differindex 18406a39bb1e..24ea6cfbc935 100644 --- a/core/res/res/drawable-xhdpi/textfield_search_empty_selected.9.png +++ b/core/res/res/drawable-xhdpi/textfield_search_empty_selected.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_search_pressed.9.png b/core/res/res/drawable-xhdpi/textfield_search_pressed.9.png Binary files differindex 0913c23ada57..815785c3dd2f 100644 --- a/core/res/res/drawable-xhdpi/textfield_search_pressed.9.png +++ b/core/res/res/drawable-xhdpi/textfield_search_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_search_selected.9.png b/core/res/res/drawable-xhdpi/textfield_search_selected.9.png Binary files differindex 7ba4d61f5543..f009cdbd6f35 100644 --- a/core/res/res/drawable-xhdpi/textfield_search_selected.9.png +++ b/core/res/res/drawable-xhdpi/textfield_search_selected.9.png diff --git a/core/res/res/drawable-xhdpi/textfield_selected.9.png b/core/res/res/drawable-xhdpi/textfield_selected.9.png Binary files differindex 275d6283c23b..963efdebb00f 100644 --- a/core/res/res/drawable-xhdpi/textfield_selected.9.png +++ b/core/res/res/drawable-xhdpi/textfield_selected.9.png diff --git a/core/res/res/drawable-xhdpi/title_bar_medium.9.png b/core/res/res/drawable-xhdpi/title_bar_medium.9.png Binary files differindex 4ef531c22a4d..109c01754f9b 100644 --- a/core/res/res/drawable-xhdpi/title_bar_medium.9.png +++ b/core/res/res/drawable-xhdpi/title_bar_medium.9.png diff --git a/core/res/res/drawable-xhdpi/title_bar_portrait.9.png b/core/res/res/drawable-xhdpi/title_bar_portrait.9.png Binary files differindex eb607c7cb995..3c91a4a69200 100644 --- a/core/res/res/drawable-xhdpi/title_bar_portrait.9.png +++ b/core/res/res/drawable-xhdpi/title_bar_portrait.9.png diff --git a/core/res/res/drawable-xhdpi/title_bar_tall.9.png b/core/res/res/drawable-xhdpi/title_bar_tall.9.png Binary files differindex 4beb1d7fee46..e986db113ae1 100644 --- a/core/res/res/drawable-xhdpi/title_bar_tall.9.png +++ b/core/res/res/drawable-xhdpi/title_bar_tall.9.png diff --git a/core/res/res/drawable-xhdpi/vpn_connected.png b/core/res/res/drawable-xhdpi/vpn_connected.png Binary files differindex 5d37ffc47ff9..1f46be2cea5d 100644 --- a/core/res/res/drawable-xhdpi/vpn_connected.png +++ b/core/res/res/drawable-xhdpi/vpn_connected.png diff --git a/core/res/res/drawable-xhdpi/vpn_disconnected.png b/core/res/res/drawable-xhdpi/vpn_disconnected.png Binary files differindex dd9ba929ad3d..847d3f52701f 100644 --- a/core/res/res/drawable-xhdpi/vpn_disconnected.png +++ b/core/res/res/drawable-xhdpi/vpn_disconnected.png diff --git a/core/res/res/drawable-xhdpi/zoom_plate.9.png b/core/res/res/drawable-xhdpi/zoom_plate.9.png Binary files differindex 5229b5fa6ff3..797215b6595a 100644 --- a/core/res/res/drawable-xhdpi/zoom_plate.9.png +++ b/core/res/res/drawable-xhdpi/zoom_plate.9.png diff --git a/core/res/res/drawable-xlarge-hdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-xlarge-hdpi/indicator_code_lock_drag_direction_green_up.png Binary files differdeleted file mode 100644 index c605607222ae..000000000000 --- a/core/res/res/drawable-xlarge-hdpi/indicator_code_lock_drag_direction_green_up.png +++ /dev/null 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 07b4837624a9..dd291644e4f3 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 @@ -80,7 +80,8 @@ android:layout_alignParentBottom="true" android:drawableLeft="@drawable/ic_emergency" style="@style/Widget.Button.Transparent" - android:drawablePadding="8dip"/> + android:drawablePadding="8dip" + android:visibility="gone"/> </RelativeLayout>> diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml index 694db50a84ee..8bc5f34a84a6 100644 --- a/core/res/res/layout/keyguard_screen_password_landscape.xml +++ b/core/res/res/layout/keyguard_screen_password_landscape.xml @@ -170,6 +170,7 @@ <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard" android:layout_width="270dip" android:layout_height="wrap_content" + android:layout_marginLeft="4dip" android:layout_marginRight="4dip" android:background="#40000000" android:layout_marginTop="5dip" @@ -190,4 +191,17 @@ android:layout_height="0dip" /> + <!-- Area to overlay FaceLock --> + <TextView android:id="@+id/faceLockAreaView" + android:visibility="gone" + android:layout_row="0" + android:layout_column="2" + android:layout_rowSpan="8" + android:layout_columnSpan="1" + android:layout_gravity="fill" + android:layout_width="0dip" + android:layout_height="0dip" + android:background="@color/facelock_color_background" + /> + </GridLayout> diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml index 27a51dad639c..2a66d7dba841 100644 --- a/core/res/res/layout/keyguard_screen_password_portrait.xml +++ b/core/res/res/layout/keyguard_screen_password_portrait.xml @@ -132,7 +132,7 @@ <!-- Numeric keyboard --> <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard" android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_marginLeft="4dip" android:layout_marginRight="4dip" android:paddingTop="4dip" android:paddingBottom="4dip" diff --git a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml index 0f2ae0c02502..8b039f7e2ff7 100644 --- a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml +++ b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml @@ -34,6 +34,9 @@ android:layout_height="wrap_content" android:gravity="center" android:singleLine="true" + android:ellipsize="marquee" + android:layout_marginRight="6dip" + android:layout_marginLeft="6dip" android:textAppearance="?android:attr/textAppearanceLarge"/> <!-- Carrier info --> @@ -44,6 +47,8 @@ android:gravity="center" android:singleLine="true" android:ellipsize="marquee" + android:layout_marginRight="6dip" + android:layout_marginLeft="6dip" android:textAppearance="?android:attr/textAppearanceMedium"/> <LinearLayout @@ -52,28 +57,6 @@ android:layout_height="wrap_content"> <LinearLayout - android:orientation="vertical" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="10dip" - android:layout_marginLeft="10dip"> - <TextView android:id="@+id/enter_puk" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center_vertical" - android:text="@android:string/keyguard_password_enter_puk_prompt" - android:textSize="30sp" - android:layout_marginBottom="10dip"/> - <TextView android:id="@+id/enter_pin" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center_vertical" - android:text="@android:string/keyguard_password_enter_pin_prompt" - android:textSize="30sp" - android:layout_marginTop="10dip"/> - </LinearLayout> - - <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_weight="1" @@ -92,14 +75,15 @@ android:background="@android:drawable/edit_text"> <!-- displays dots as user enters puk --> - <TextView android:id="@+id/pukDisplay" + <EditText android:id="@+id/pukDisplay" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:maxLines="1" - android:textAppearance="?android:attr/textAppearanceLargeInverse" android:textStyle="bold" android:inputType="textPassword" + android:textColor="#000" + android:hint="@android:string/keyguard_password_enter_puk_prompt" /> <ImageButton android:id="@+id/pukDel" @@ -122,14 +106,15 @@ android:background="@android:drawable/edit_text"> <!-- displays dots as user enters new pin --> - <TextView android:id="@+id/pinDisplay" + <EditText android:id="@+id/pinDisplay" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:maxLines="1" - android:textAppearance="?android:attr/textAppearanceLargeInverse" android:textStyle="bold" android:inputType="textPassword" + android:textColor="#000" + android:hint="@android:string/keyguard_password_enter_pin_prompt" /> <ImageButton android:id="@+id/pinDel" diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml index d71dbffd8f9d..2778f4e8446d 100644 --- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml +++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml @@ -160,4 +160,18 @@ android:layout_height="0dip" /> + <!-- Area to overlay FaceLock --> + <TextView android:id="@+id/faceLockAreaView" + android:visibility="gone" + android:layout_row="0" + android:layout_column="1" + android:layout_rowSpan="7" + android:layout_columnSpan="1" + android:layout_gravity="fill" + android:layout_marginLeft="8dip" + android:layout_width="0dip" + android:layout_height="0dip" + android:background="@color/facelock_color_background" + /> + </GridLayout> diff --git a/core/res/res/layout/number_picker.xml b/core/res/res/layout/number_picker.xml index f2f524caf813..807daf2b2dae 100644 --- a/core/res/res/layout/number_picker.xml +++ b/core/res/res/layout/number_picker.xml @@ -23,8 +23,6 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" style="?android:attr/numberPickerUpButtonStyle" - android:paddingTop="22dip" - android:paddingBottom="22dip" android:contentDescription="@string/number_picker_increment_button" /> <EditText android:id="@+id/numberpicker_input" @@ -36,8 +34,6 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" style="?android:attr/numberPickerDownButtonStyle" - android:paddingTop="22dip" - android:paddingBottom="22dip" android:contentDescription="@string/number_picker_decrement_button" /> </merge> diff --git a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml index ac4d1e43f7c4..f3f19574a636 100644 --- a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml +++ b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml @@ -4,8 +4,8 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="vertical" - android:paddingLeft="8dp" - android:paddingRight="8dp" + android:paddingLeft="12dp" + android:paddingRight="12dp" > <TextView android:id="@+id/title" android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title" diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml index 082c5ec031c0..1fdc1bf3edca 100644 --- a/core/res/res/layout/text_edit_suggestion_item.xml +++ b/core/res/res/layout/text_edit_suggestion_item.xml @@ -15,7 +15,7 @@ --> <TextView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="16dip" android:paddingRight="16dip" @@ -23,6 +23,7 @@ android:paddingBottom="8dip" android:layout_gravity="left|center_vertical" android:singleLine="true" + android:drawablePadding="8dip" android:ellipsize="marquee" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@android:color/dim_foreground_light" /> diff --git a/core/res/res/values-mcc204/strings.xml b/core/res/res/values-mcc204/strings.xml index c3fff3d6df81..134e9d2007cb 100644 --- a/core/res/res/values-mcc204/strings.xml +++ b/core/res/res/values-mcc204/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- A string used to replace %s in a URL to fill in the locale for countries --> - <!-- whose locale we don't natively support. A 0 length string triggers no replacement --> + <!-- whose locale we don't natively support. A 0 length string triggers no replacement. Do not translate --> <string name="locale_replacement">nl_nl</string> </resources> diff --git a/core/res/res/values-mcc230/strings.xml b/core/res/res/values-mcc230/strings.xml index 559b858cbde0..3078bf8cf1cd 100644 --- a/core/res/res/values-mcc230/strings.xml +++ b/core/res/res/values-mcc230/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- A string used to replace %s in a URL to fill in the locale for countries --> - <!-- whose locale we don't natively support. A 0 length string triggers no replacement --> + <!-- whose locale we don't natively support. A 0 length string triggers no replacement. Do not translate --> <string name="locale_replacement">cs_cz</string> </resources> diff --git a/core/res/res/values-mcc232/strings.xml b/core/res/res/values-mcc232/strings.xml index 494770f213dd..809e4a08be4a 100644 --- a/core/res/res/values-mcc232/strings.xml +++ b/core/res/res/values-mcc232/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- A string used to replace %s in a URL to fill in the locale for countries --> - <!-- whose locale we don't natively support. A 0 length string triggers no replacement --> + <!-- whose locale we don't natively support. A 0 length string triggers no replacement. Do not translate --> <string name="locale_replacement">de_at</string> </resources> diff --git a/core/res/res/values-mcc234/strings.xml b/core/res/res/values-mcc234/strings.xml index 2e6a3f327528..676defee3001 100644 --- a/core/res/res/values-mcc234/strings.xml +++ b/core/res/res/values-mcc234/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- A string used to replace %s in a URL to fill in the locale for countries --> - <!-- whose locale we don't natively support. A 0 length string triggers no replacement --> + <!-- whose locale we don't natively support. A 0 length string triggers no replacement. Do not translate --> <string name="locale_replacement">en_gb</string> </resources> diff --git a/core/res/res/values-mcc260/strings.xml b/core/res/res/values-mcc260/strings.xml index 20c19ddb0f7e..90f25218fe30 100644 --- a/core/res/res/values-mcc260/strings.xml +++ b/core/res/res/values-mcc260/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- A string used to replace %s in a URL to fill in the locale for countries --> - <!-- whose locale we don't natively support. A 0 length string triggers no replacement --> + <!-- whose locale we don't natively support. A 0 length string triggers no replacement. Do not translate --> <string name="locale_replacement">pl_pl</string> </resources> diff --git a/core/res/res/values-mcc262/strings.xml b/core/res/res/values-mcc262/strings.xml index 8ca0e31e603a..ae323b85533f 100644 --- a/core/res/res/values-mcc262/strings.xml +++ b/core/res/res/values-mcc262/strings.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- A string used to replace %s in a URL to fill in the locale for countries --> - <!-- whose locale we don't natively support. A 0 length string triggers no replacement --> + <!-- whose locale we don't natively support. A 0 length string triggers no replacement. Do not translate --> <string name="locale_replacement">de_de</string> </resources> diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml index 13bbac60f5c8..7fa76589957d 100644 --- a/core/res/res/values-sw600dp/config.xml +++ b/core/res/res/values-sw600dp/config.xml @@ -32,5 +32,8 @@ <!-- see comment in values/config.xml --> <dimen name="config_prefDialogWidth">580dp</dimen> + <!-- If true, the screen can be rotated via the accelerometer in all 4 + rotations as the default behavior. --> + <bool name="config_allowAllRotations">true</bool> </resources> diff --git a/core/res/res/values-zh-rTW/donottranslate-cldr.xml b/core/res/res/values-zh-rTW/donottranslate-cldr.xml index 06c9bccc5c27..a43f8572850b 100644 --- a/core/res/res/values-zh-rTW/donottranslate-cldr.xml +++ b/core/res/res/values-zh-rTW/donottranslate-cldr.xml @@ -61,21 +61,21 @@ <string name="day_of_week_long_friday">星期五</string> <string name="day_of_week_long_saturday">星期六</string> - <string name="day_of_week_medium_sunday">周日</string> - <string name="day_of_week_medium_monday">周一</string> - <string name="day_of_week_medium_tuesday">周二</string> - <string name="day_of_week_medium_wednesday">周三</string> - <string name="day_of_week_medium_thursday">周四</string> - <string name="day_of_week_medium_friday">周五</string> - <string name="day_of_week_medium_saturday">周六</string> + <string name="day_of_week_medium_sunday">週日</string> + <string name="day_of_week_medium_monday">週一</string> + <string name="day_of_week_medium_tuesday">週二</string> + <string name="day_of_week_medium_wednesday">週三</string> + <string name="day_of_week_medium_thursday">週四</string> + <string name="day_of_week_medium_friday">週五</string> + <string name="day_of_week_medium_saturday">週六</string> - <string name="day_of_week_short_sunday">周日</string> - <string name="day_of_week_short_monday">周一</string> - <string name="day_of_week_short_tuesday">周二</string> - <string name="day_of_week_short_wednesday">周三</string> - <string name="day_of_week_short_thursday">周四</string> - <string name="day_of_week_short_friday">周五</string> - <string name="day_of_week_short_saturday">周六</string> + <string name="day_of_week_short_sunday">週日</string> + <string name="day_of_week_short_monday">週一</string> + <string name="day_of_week_short_tuesday">週二</string> + <string name="day_of_week_short_wednesday">週三</string> + <string name="day_of_week_short_thursday">週四</string> + <string name="day_of_week_short_friday">週五</string> + <string name="day_of_week_short_saturday">週六</string> <string name="day_of_week_shortest_sunday">日</string> <string name="day_of_week_shortest_monday">一</string> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 847afa051440..727c6ea36d58 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -710,11 +710,12 @@ <enum name="preferExternal" value="2" /> </attr> - <!-- Extra options for an activity's UI. If specified on the application + <!-- Extra options for an activity's UI. Applies to either the {@code <activity>} or + {@code <application>} tag. If specified on the {@code <application>} tag these will be considered defaults for all activities in the application. --> <attr name="uiOptions"> - <!-- No extra UI options. --> + <!-- No extra UI options. This is the default. --> <flag name="none" value="0" /> <!-- Split the options menu into a separate bar at the bottom of the screen when severely constrained for horizontal space. @@ -1561,8 +1562,21 @@ <enum name="xhdpi" value="320" /> </attr> </declare-styleable> - - + + <!-- The attribute that holds a Base64-encoded public key. --> + <attr name="publicKey" format="string" /> + + <!-- Attributes relating to a package verifier --> + <declare-styleable name="AndroidManifestPackageVerifier" parent="AndroidManifest"> + <!-- Specifies the Java-style package name that defines this + package verifier. --> + <attr name="name" /> + + <!-- The Base64 encoded public key of the package verifier's + signature. --> + <attr name="publicKey" /> + </declare-styleable> + <!-- Declaration of an {@link android.content.Intent} object in XML. May also include zero or more {@link #IntentCategory <category> and {@link #Extra <extra>} tags. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 1e5358e20dcb..ae39760a2a01 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -138,6 +138,18 @@ <item>"0,1"</item> </string-array> + <!-- Set of NetworkInfo.getType() that reflect data usage. --> + <integer-array translatable="false" name="config_data_usage_network_types"> + <item>0</item> <!-- TYPE_MOBILE --> + <item>2</item> <!-- TYPE_MOBILE_MMS --> + <item>3</item> <!-- TYPE_MOBILE_SUPL --> + <item>4</item> <!-- TYPE_MOBILE_DUN --> + <item>5</item> <!-- TYPE_MOBILE_HIPRI --> + <item>10</item> <!-- TYPE_MOBILE_FOTA --> + <item>11</item> <!-- TYPE_MOBILE_IMS --> + <item>12</item> <!-- TYPE_MOBILE_CBS --> + </integer-array> + <!-- The maximum duration (in milliseconds) we expect a network transition to take --> <integer name="config_networkTransitionTimeout">60000</integer> @@ -231,7 +243,7 @@ <!-- If true, the screen can be rotated via the accelerometer in all 4 rotations as the default behavior. --> - <bool name="config_allowAllRotations">true</bool> + <bool name="config_allowAllRotations">false</bool> <!-- If true, the direction rotation is applied to get to an application's requested orientation is reversed. Normally, the model is that landscape is @@ -400,9 +412,9 @@ <!-- Diable lockscreen rotation by default --> <bool name="config_enableLockScreenRotation">false</bool> - <!-- Diable puk unlockscreen by default. + <!-- Enable puk unlockscreen by default. If unlock screen is disabled, the puk should be unlocked through Emergency Dialer --> - <bool name="config_enable_puk_unlock_screen">false</bool> + <bool name="config_enable_puk_unlock_screen">true</bool> <!-- Control the behavior when the user long presses the home button. 0 - Nothing diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 848fb8bdb745..97d5afe8cfdf 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1768,6 +1768,7 @@ <public type="attr" name="listPreferredItemPaddingLeft" id="0x010103a3" /> <public type="attr" name="listPreferredItemPaddingRight" id="0x010103a4" /> <public type="attr" name="requiresFadingEdge" id="0x010103a5" /> + <public type="attr" name="publicKey" id="0x010103a6" /> <public type="style" name="TextAppearance.SuggestionHighlight" id="0x01030118" /> <public type="style" name="Theme.Holo.Light.DarkActionBar" id="0x01030119" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index e093fa97d3cc..2d5d4cc8ff29 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -41,9 +41,13 @@ <string name="untitled"><untitled></string> <!-- Used to replace a range of characters in text that is too wide - for the space allocated to it. --> + for the space allocated to it (three dots). --> <string name="ellipsis">\u2026</string> + <!-- Used to replace a range of characters in text that is too wide + for the space allocated to it (two dots). --> + <string name="ellipsis_two_dots">\u2025</string> + <!-- How to display the lack of a phone number --> <string name="emptyPhoneNumber">(No phone number)</string> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 88b45fdfdcd0..b6e213c79f27 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -524,10 +524,14 @@ please see styles_device_defaults.xml. <style name="Widget.ImageButton.NumberPickerUpButton"> <item name="android:background">@android:drawable/numberpicker_up_btn</item> + <item name="android:paddingTop">22dip</item> + <item name="android:paddingBottom">22dip</item> </style> <style name="Widget.ImageButton.NumberPickerDownButton"> <item name="android:background">@android:drawable/numberpicker_down_btn</item> + <item name="android:paddingTop">22dip</item> + <item name="android:paddingBottom">22dip</item> </style> <style name="Widget.EditText.NumberPickerInputText"> @@ -1651,15 +1655,15 @@ please see styles_device_defaults.xml. <style name="Widget.Holo.ImageButton.NumberPickerUpButton"> <item name="android:background">@null</item> <item name="android:src">@android:drawable/numberpicker_up_btn_holo_dark</item> - <item name="android:paddingTop">26dip</item> - <item name="android:paddingBottom">26dip</item> + <item name="android:paddingTop">16dip</item> + <item name="android:paddingBottom">36dip</item> </style> <style name="Widget.Holo.ImageButton.NumberPickerDownButton"> <item name="android:background">@null</item> <item name="android:src">@android:drawable/numberpicker_down_btn_holo_dark</item> - <item name="android:paddingTop">26dip</item> - <item name="android:paddingBottom">26dip</item> + <item name="android:paddingTop">36dip</item> + <item name="android:paddingBottom">16dip</item> </style> <style name="Widget.Holo.EditText.NumberPickerInputText"> diff --git a/core/tests/coretests/apks/install_verifier_bad/Android.mk b/core/tests/coretests/apks/install_verifier_bad/Android.mk new file mode 100644 index 000000000000..b50cfd0410d1 --- /dev/null +++ b/core/tests/coretests/apks/install_verifier_bad/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_verifier_bad + +include $(BUILD_PACKAGE) + diff --git a/core/tests/coretests/apks/install_verifier_bad/AndroidManifest.xml b/core/tests/coretests/apks/install_verifier_bad/AndroidManifest.xml new file mode 100644 index 000000000000..0170cdd01c03 --- /dev/null +++ b/core/tests/coretests/apks/install_verifier_bad/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.frameworks.coretests.install_verifier_bad"> + + <package-verifier android:name="com.android.frameworks.coretests.nonexistent" android:publicKey="Zm9vYmFy" /> + + <application android:hasCode="false"> + </application> +</manifest> diff --git a/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml b/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml new file mode 100644 index 000000000000..3b8b3b1af9b5 --- /dev/null +++ b/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- Just need this dummy file to have something to build. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="dummy">dummy</string> +</resources> diff --git a/core/tests/coretests/apks/install_verifier_good/Android.mk b/core/tests/coretests/apks/install_verifier_good/Android.mk new file mode 100644 index 000000000000..a48a80e2c92e --- /dev/null +++ b/core/tests/coretests/apks/install_verifier_good/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_verifier_good + +include $(BUILD_PACKAGE) diff --git a/core/tests/coretests/apks/install_verifier_good/AndroidManifest.xml b/core/tests/coretests/apks/install_verifier_good/AndroidManifest.xml new file mode 100644 index 000000000000..90135a5c01e7 --- /dev/null +++ b/core/tests/coretests/apks/install_verifier_good/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.frameworks.coretests.install_verifier_bad"> + + <package-verifier android:name="com.android.frameworks.coretests" android:publicKey="MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAnHgFkqwNXTgc3qpl7MimAG42SAxtcgexIBG+UIY6q+K1XQCa33FG1vIgIoDHzU172yYkO4qAbCazSxN1I6SSaCJJBNwBST58Cs8aBch09psDe2AwnZB00kKA4WutKoc0NhlR6vcqSC0JsgSxh14SrJjBqnc9aAC56v3lbVi+2OjaFvmjYAmcN6g0pt/tt7a0SgSeB6Jp/M8sVJbyzzbWTfkKO42PNKO6q0z1M3GrJ3GbO6WHVK0MU/wU4dtF1R4jT7vpPJuk7fnOVCYTUOxTVge/aaL/SqB9tffqIA0JpsG0niFAL4ntEZCJOqtakYDxUugvhaRXU89fwZBxxe7IJwIBAw==" /> + + <application android:hasCode="false"> + </application> +</manifest> diff --git a/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml b/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml new file mode 100644 index 000000000000..3b8b3b1af9b5 --- /dev/null +++ b/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- Just need this dummy file to have something to build. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="dummy">dummy</string> +</resources> diff --git a/core/tests/coretests/src/android/net/http/AbstractProxyTest.java b/core/tests/coretests/src/android/net/http/AbstractProxyTest.java index ee4ce95202fd..48912329438d 100644 --- a/core/tests/coretests/src/android/net/http/AbstractProxyTest.java +++ b/core/tests/coretests/src/android/net/http/AbstractProxyTest.java @@ -219,6 +219,23 @@ public abstract class AbstractProxyTest extends TestCase { assertEquals("GET /bar HTTP/1.1", recordedRequest.getRequestLine()); } + // http://b/5372438 + public void testRetryWithProxy() throws Exception { + server.enqueue(new MockResponse() + .setSocketPolicy(SocketPolicy.DISCONNECT_AT_START)); + server.play(); + + HttpClient httpProxyClient = newHttpClient(); + HttpGet request = new HttpGet("http://android.com/foo"); + ProxyConfig.REQUEST_PARAMETER.configure(server, httpProxyClient, request); + + try { + httpProxyClient.execute(request); + fail(); + } catch (IOException expected) { + } + } + enum ProxyConfig { PROXY_SYSTEM_PROPERTY() { @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk new file mode 100644 index 000000000000..db27cdcfac7a --- /dev/null +++ b/data/fonts/Android.mk @@ -0,0 +1,61 @@ +# 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. + +# We have to use BUILD_PREBUILT instead of PRODUCT_COPY_FIES, +# because SMALLER_FONT_FOOTPRINT is only available in Android.mks. + +LOCAL_PATH := $(call my-dir) + +ifeq ($(SMALLER_FONT_FOOTPRINT),true) +droidsans_fallback_src := DroidSansFallback.ttf +extra_droidsans_fonts := +else +droidsans_fallback_src := DroidSansFallbackFull.ttf +extra_droidsans_fonts := DroidSans.ttf DroidSans-Bold.ttf DroidSansEthiopic-Regular.ttf +endif + +include $(CLEAR_VARS) +LOCAL_MODULE := DroidSansFallback.ttf +LOCAL_SRC_FILES := $(droidsans_fallback_src) +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts +LOCAL_REQUIRED_MODULES := $(extra_droidsans_fonts) +droidsans_fallback_src := +extra_droidsans_fonts := +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := DroidSans.ttf +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := DroidSans-Bold.ttf +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := DroidSansEthiopic-Regular.ttf +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts +include $(BUILD_PREBUILT) diff --git a/data/fonts/AndroidClock.ttf b/data/fonts/AndroidClock.ttf Binary files differindex 7ebc9634b878..3fa6d8867770 100644 --- a/data/fonts/AndroidClock.ttf +++ b/data/fonts/AndroidClock.ttf diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf Binary files differindex 7ebc9634b878..3fa6d8867770 100644 --- a/data/fonts/AndroidClock_Highlight.ttf +++ b/data/fonts/AndroidClock_Highlight.ttf diff --git a/data/fonts/AndroidClock_Solid.ttf b/data/fonts/AndroidClock_Solid.ttf Binary files differindex 7ebc9634b878..3fa6d8867770 100644 --- a/data/fonts/AndroidClock_Solid.ttf +++ b/data/fonts/AndroidClock_Solid.ttf diff --git a/data/fonts/Lohit_Hindi.ttf b/data/fonts/Lohit_Hindi.ttf Binary files differdeleted file mode 100644 index 73caae34aac0..000000000000 --- a/data/fonts/Lohit_Hindi.ttf +++ /dev/null diff --git a/data/fonts/Roboto-Bold.ttf b/data/fonts/Roboto-Bold.ttf Binary files differindex c716bbbcadf0..e5d828d8b43d 100644 --- a/data/fonts/Roboto-Bold.ttf +++ b/data/fonts/Roboto-Bold.ttf diff --git a/data/fonts/Roboto-BoldItalic.ttf b/data/fonts/Roboto-BoldItalic.ttf Binary files differindex eeb5120ac6dc..d8fa3ae88d83 100644 --- a/data/fonts/Roboto-BoldItalic.ttf +++ b/data/fonts/Roboto-BoldItalic.ttf diff --git a/data/fonts/Roboto-Italic.ttf b/data/fonts/Roboto-Italic.ttf Binary files differindex 1e88d3eba2cc..6682d17b0bae 100644 --- a/data/fonts/Roboto-Italic.ttf +++ b/data/fonts/Roboto-Italic.ttf diff --git a/data/fonts/Roboto-Regular.ttf b/data/fonts/Roboto-Regular.ttf Binary files differindex 3033027401fa..153c60882bb8 100644 --- a/data/fonts/Roboto-Regular.ttf +++ b/data/fonts/Roboto-Regular.ttf diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml index e4685589f834..881233a1eb5a 100644 --- a/data/fonts/fallback_fonts.xml +++ b/data/fonts/fallback_fonts.xml @@ -56,7 +56,7 @@ </family> <family> <fileset> - <file>Lohit_Hindi.ttf</file> + <file>Lohit-Devanagari.ttf</file> </fileset> </family> <family> diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk index 5bac8f00e479..3f51eb3720a4 100644 --- a/data/fonts/fonts.mk +++ b/data/fonts/fonts.mk @@ -30,7 +30,6 @@ PRODUCT_COPY_FILES := \ frameworks/base/data/fonts/DroidSerif-Italic.ttf:system/fonts/DroidSerif-Italic.ttf \ frameworks/base/data/fonts/DroidSerif-BoldItalic.ttf:system/fonts/DroidSerif-BoldItalic.ttf \ frameworks/base/data/fonts/DroidSansMono.ttf:system/fonts/DroidSansMono.ttf \ - frameworks/base/data/fonts/Lohit_Hindi.ttf:system/fonts/Lohit_Hindi.ttf \ frameworks/base/data/fonts/DroidSansArmenian.ttf:system/fonts/DroidSansArmenian.ttf \ frameworks/base/data/fonts/DroidSansGeorgian.ttf:system/fonts/DroidSansGeorgian.ttf \ frameworks/base/data/fonts/Clockopia.ttf:system/fonts/Clockopia.ttf \ @@ -40,16 +39,7 @@ PRODUCT_COPY_FILES := \ frameworks/base/data/fonts/system_fonts.xml:system/etc/system_fonts.xml \ frameworks/base/data/fonts/fallback_fonts.xml:system/etc/fallback_fonts.xml -# Next, include additional fonts, depending on how much space we have -ifeq ($(SMALLER_FONT_FOOTPRINT),true) -# Smaller fonts alternatives -PRODUCT_COPY_FILES += \ - frameworks/base/data/fonts/DroidSansFallback.ttf:system/fonts/DroidSansFallback.ttf -else -# Full font set alternatives -PRODUCT_COPY_FILES += \ - frameworks/base/data/fonts/DroidSansFallbackFull.ttf:system/fonts/DroidSansFallback.ttf \ - frameworks/base/data/fonts/DroidSans.ttf:system/fonts/DroidSans.ttf \ - frameworks/base/data/fonts/DroidSans-Bold.ttf:system/fonts/DroidSans-Bold.ttf \ - frameworks/base/data/fonts/DroidSansEthiopic-Regular.ttf:system/fonts/DroidSansEthiopic-Regular.ttf -endif +# Next, include additional fonts, depending on how much space we have. +# Details see module definitions in Android.mk. +PRODUCT_PACKAGES := \ + DroidSansFallback.ttf diff --git a/data/sounds/effects/ogg/Effect_Tick.ogg b/data/sounds/effects/ogg/Effect_Tick.ogg Binary files differindex b3790199b8b1..c8a5c36e9550 100644 --- a/data/sounds/effects/ogg/Effect_Tick.ogg +++ b/data/sounds/effects/ogg/Effect_Tick.ogg diff --git a/data/sounds/effects/ogg/KeypressDelete_14.ogg b/data/sounds/effects/ogg/KeypressDelete_14.ogg Binary files differindex aa4349dd1a24..0baea25cb756 100644 --- a/data/sounds/effects/ogg/KeypressDelete_14.ogg +++ b/data/sounds/effects/ogg/KeypressDelete_14.ogg diff --git a/data/sounds/effects/ogg/KeypressDelete_49.ogg b/data/sounds/effects/ogg/KeypressDelete_49.ogg Binary files differindex aa4349dd1a24..f5e9deb5c8cd 100644 --- a/data/sounds/effects/ogg/KeypressDelete_49.ogg +++ b/data/sounds/effects/ogg/KeypressDelete_49.ogg diff --git a/data/sounds/effects/ogg/KeypressReturn_14.ogg b/data/sounds/effects/ogg/KeypressReturn_14.ogg Binary files differindex 2244a4220097..86a5a0e9a2dc 100644 --- a/data/sounds/effects/ogg/KeypressReturn_14.ogg +++ b/data/sounds/effects/ogg/KeypressReturn_14.ogg diff --git a/data/sounds/effects/ogg/KeypressReturn_49.ogg b/data/sounds/effects/ogg/KeypressReturn_49.ogg Binary files differindex 2244a4220097..b0ddee5b7692 100644 --- a/data/sounds/effects/ogg/KeypressReturn_49.ogg +++ b/data/sounds/effects/ogg/KeypressReturn_49.ogg diff --git a/data/sounds/effects/ogg/KeypressSpacebar_14.ogg b/data/sounds/effects/ogg/KeypressSpacebar_14.ogg Binary files differindex 56ea15e289e0..058534a28dd6 100644 --- a/data/sounds/effects/ogg/KeypressSpacebar_14.ogg +++ b/data/sounds/effects/ogg/KeypressSpacebar_14.ogg diff --git a/data/sounds/effects/ogg/KeypressSpacebar_49.ogg b/data/sounds/effects/ogg/KeypressSpacebar_49.ogg Binary files differindex 56ea15e289e0..3866e0e91cc2 100644 --- a/data/sounds/effects/ogg/KeypressSpacebar_49.ogg +++ b/data/sounds/effects/ogg/KeypressSpacebar_49.ogg diff --git a/data/sounds/effects/ogg/KeypressStandard_14.ogg b/data/sounds/effects/ogg/KeypressStandard_14.ogg Binary files differindex 8df7214bdcca..317c8f3ab42e 100644 --- a/data/sounds/effects/ogg/KeypressStandard_14.ogg +++ b/data/sounds/effects/ogg/KeypressStandard_14.ogg diff --git a/data/sounds/effects/ogg/KeypressStandard_49.ogg b/data/sounds/effects/ogg/KeypressStandard_49.ogg Binary files differindex 8df7214bdcca..893bb522cc7b 100644 --- a/data/sounds/effects/ogg/KeypressStandard_49.ogg +++ b/data/sounds/effects/ogg/KeypressStandard_49.ogg diff --git a/docs/html/guide/appendix/media-formats.jd b/docs/html/guide/appendix/media-formats.jd index e128a1cc0347..ccc63a214a64 100644 --- a/docs/html/guide/appendix/media-formats.jd +++ b/docs/html/guide/appendix/media-formats.jd @@ -37,11 +37,16 @@ page.title=Android Supported Media Formats <ul> <li>RTSP (RTP, SDP)</li> - <li>HTTP progressive streaming</li> - <li>HTTP live streaming <a href="http://tools.ietf.org/html/draft-pantos-http-live-streaming-05">draft protocol</a> (Android 3.0 and above)</li> + <li>HTTP/HTTPS progressive streaming</li> + <li>HTTP/HTTPS live streaming <a href="http://tools.ietf.org/html/draft-pantos-http-live-streaming">draft protocol</a>: <ul> + <li>MPEG-2 TS media files only</li> + <li>Protocol version 3 (Android 4.0 and above)</li> + <li>Protocol version 2 (Android 3.x)</li> + <li>Not supported before Android 3.0</li> + </ul></li> </ul> -<p class="note"><strong>Note:</strong> HTTPS is not supported at this time.</p> +<p class="note"><strong>Note:</strong> HTTPS is not supported before Android 3.1.</p> <h2 id="core">Core Media Formats</h2> @@ -71,7 +76,11 @@ page.title=Android Supported Media Formats <td style="text-align: center;"><big>•</big></td> <td rowspan="3">Mono/Stereo content in any combination of standard bit rates up to 160 kbps and sampling rates from 8 to 48kHz</td> -<td rowspan="3">3GPP (.3gp), and MPEG-4 (.mp4, .m4a). ADTS raw AAC (.aac, decode only, ADIF not supported, Android 3.1+). </td> +<td rowspan="3"> + • 3GPP (.3gp)<br> + • MPEG-4 (.mp4, .m4a)<br> + • ADTS raw AAC (.aac, decode in Android 3.1+, encode in Android 4.0+, ADIF not supported)<br> + • MPEG-TS (.ts, not seekable, Android 3.0+)</td> </tr> <tr> @@ -91,8 +100,8 @@ rates up to 160 kbps and sampling rates from 8 to 48kHz</td> <td style="text-align: center;"><big>•</big></td> <td style="text-align: center;"><big>•</big></td> <td>4.75 to 12.2 kbps sampled @ 8kHz</td> -<td>3GPP (.3gp) -</td> +<td> + 3GPP (.3gp)</td> </tr> <tr> @@ -100,19 +109,21 @@ rates up to 160 kbps and sampling rates from 8 to 48kHz</td> <td style="text-align: center;"><big>•</big></td> <td style="text-align: center;"><big>•</big></td> <td>9 rates from 6.60 kbit/s to 23.85 kbit/s sampled @ 16kHz</td> -<td>3GPP (.3gp)</td> +<td> + 3GPP (.3gp)</td> </tr> <tr> <td>FLAC</td> <td> </td> -<td style="text-align: center;"><big>•</big><br><small>(Android 3.1+)</small></td> +<td style="text-align: center;" nowrap><big>•</big><br><small>(Android 3.1+)</small></td> <td>Mono/Stereo (no multichannel). Sample rates up to 48 kHz (but up to 44.1 kHz is recommended on devices with 44.1 kHz output, as the 48 to 44.1 kHz downsampler does not include a low-pass filter). 16-bit recommended; no dither applied for 24-bit. </td> -<td>FLAC (.flac) only</td> +<td> + FLAC (.flac) only</td> </tr> <tr> @@ -121,7 +132,8 @@ no dither applied for 24-bit. <td style="text-align: center;"><big>•</big></td> <td>Mono/Stereo 8-320Kbps constant (CBR) or variable bit-rate (VBR) </td> -<td>MP3 (.mp3)</td> +<td> + MP3 (.mp3)</td> </tr> <tr> @@ -129,15 +141,21 @@ no dither applied for 24-bit. <td> </td> <td style="text-align: center;"><big>•</big></td> <td>MIDI Type 0 and 1. DLS Version 1 and 2. XMF and Mobile XMF. Support for ringtone formats RTTTL/RTX, OTA, and iMelody </td> -<td>Type 0 and 1 (.mid, .xmf, .mxmf). Also RTTTL/RTX (.rtttl, .rtx), OTA (.ota), and iMelody (.imy)</td> +<td> + • Type 0 and 1 (.mid, .xmf, .mxmf)<br> + • RTTTL/RTX (.rtttl, .rtx)<br> + • OTA (.ota)<br> + • iMelody (.imy)</td> </tr> <tr> -<td>Ogg Vorbis</td> +<td>Vorbis</td> <td> </td> <td style="text-align: center;"><big>•</big></td> <td> </td> -<td>Ogg (.ogg)</td> +<td> + • Ogg (.ogg)<br> + • Matroska (.mkv, Android 4.0+)</td> </tr> <tr> @@ -145,16 +163,18 @@ no dither applied for 24-bit. <td> </td> <td style="text-align: center;"><big>•</big></td> <td>8- and 16-bit linear PCM (rates up to limit of hardware)</td> -<td>WAVE (.wav)</td> +<td> + WAVE (.wav)</td> </tr> <tr> -<td rowspan="4">Image</td> +<td rowspan="5">Image</td> <td>JPEG</td> <td style="text-align: center;"><big>•</big></td> <td style="text-align: center;"><big>•</big></td> <td>Base+progressive</td> -<td>JPEG (.jpg)</td> +<td> + JPEG (.jpg)</td> </tr> <tr> @@ -162,7 +182,8 @@ no dither applied for 24-bit. <td> </td> <td style="text-align: center;"><big>•</big></td> <td> </td> -<td>GIF (.gif)</td> +<td> + GIF (.gif)</td> </tr> <tr> @@ -170,7 +191,8 @@ no dither applied for 24-bit. <td style="text-align: center;"><big>•</big></td> <td style="text-align: center;"><big>•</big></td> <td> </td> -<td>PNG (.png)</td> +<td> + PNG (.png)</td> </tr> <tr> @@ -178,7 +200,17 @@ no dither applied for 24-bit. <td> </td> <td style="text-align: center;"><big>•</big></td> <td> </td> -<td>BMP (.bmp)</td> +<td> + BMP (.bmp)</td> +</tr> + +<tr> +<td>WEBP</td> +<td style="text-align: center;" nowrap><big>•</big><br><small>(Android 4.0+)</small></td> +<td style="text-align: center;" nowrap><big>•</big><br><small>(Android 4.0+)</small></td> +<td> </td> +<td> + WebP (.webp)</td> </tr> @@ -188,15 +220,20 @@ no dither applied for 24-bit. <td style="text-align: center;"><big>•</big></td> <td style="text-align: center;"><big>•</big></td> <td> </td> -<td>3GPP (.3gp) and MPEG-4 (.mp4)</td> +<td> + • 3GPP (.3gp)<br> + • MPEG-4 (.mp4)</td> </tr> <tr> <td>H.264 AVC</td> <td style="text-align: center;" nowrap><big>•</big><br><small>(Android 3.0+)</small></td> -<td style="text-align: center;"><big>•</big></td> +<td style="text-align: center;" nowrap><big>•</big></td> <td>Baseline Profile (BP)</td> -<td>3GPP (.3gp) and MPEG-4 (.mp4). MPEG-TS (.ts, AAC audio only, not seekable, Android 3.0+)</td> +<td> + • 3GPP (.3gp)<br> + • MPEG-4 (.mp4)<br> + • MPEG-TS (.ts, AAC audio only, not seekable, Android 3.0+)</td> </tr> <tr> @@ -204,15 +241,18 @@ no dither applied for 24-bit. <td> </td> <td style="text-align: center;"><big>•</big></td> <td> </td> -<td>3GPP (.3gp)</td> +<td> + 3GPP (.3gp)</td> </tr> <tr> <td>VP8</td> <td> </td> -<td style="text-align: center;"><big>•</big><br><small>(Android 2.3.3+)</small></td> -<td> </td> -<td><a href="http://www.webmproject.org/">WebM</a> (.webm)</td> +<td style="text-align: center;" nowrap><big>•</big><br><small>(Android 2.3.3+)</small></td> +<td>Streamable only in Android 4.0 and above</td> +<td> + • <a href="http://www.webmproject.org/">WebM</a> (.webm)<br> + • Matroska (.mkv, Android 4.0+)</td> </tr> </tbody></table> @@ -220,7 +260,7 @@ no dither applied for 24-bit. <h2 id="recommendations">Video Encoding Recommendations</h2> -<p>Table 2, below, lists examples of video encoding profiles and parameters that the Android media framework supports for playback. In addition to these encoding parameter recommendations, a device's available video recording profiles can be used as a proxy for media playback capabilities. These profiles can be inspected using the {@link android.media.CamcorderProfile CamcorderProfile} class, which is available since API level 8.</p> +<p>Table 2, below, lists examples of video encoding profiles and parameters that the Android media framework supports for playback. In addition to these encoding parameter recommendations, a device's available <em>video recording</em> profiles can be used as a proxy for media playback capabilities. These profiles can be inspected using the {@link android.media.CamcorderProfile CamcorderProfile} class, which is available since API level 8.</p> <p class="table-caption" id="encoding-recommendations-table"><strong>Table 2.</strong> Examples of supported video encoding parameters.</p> @@ -228,45 +268,53 @@ no dither applied for 24-bit. <thead> <tr> <th> </th> - <th style="background-color:#f3f3f3;font-weight:normal">Lower quality</th> - <th style="background-color:#f3f3f3;font-weight:normal">Higher quality</th> + <th style="background-color:#f3f3f3;font-weight:normal"><acronym title="Standard definition">SD</a> (Low quality)</th> + <th style="background-color:#f3f3f3;font-weight:normal"><acronym title="Standard definition">SD</a> (High quality)</th> + <th style="background-color:#f3f3f3;font-weight:normal"><acronym title="High definition">HD</a> (Not available on all devices)</th> </tr> </thead> <tbody> <tr> <th>Video codec</th> - <td>H.264 Baseline Profile</th> - <td>H.264 Baseline Profile</th> + <td>H.264 Baseline Profile</td> + <td>H.264 Baseline Profile</td> + <td>H.264 Baseline Profile</td> </tr> <tr> <th>Video resolution</th> - <td>176 x 144 px</th> - <td>480 x 360 px</th> + <td>176 x 144 px</td> + <td>480 x 360 px</td> + <td>1280 x 720 px</td> </tr> <tr> <th>Video frame rate</th> - <td>12 fps</th> - <td>30 fps</th> + <td>12 fps</td> + <td>30 fps</td> + <td>30 fps</td> </tr> <tr> <th>Video bitrate</th> - <td>56 Kbps</th> - <td>500 Kbps</th> + <td>56 Kbps</td> + <td>500 Kbps</td> + <td>2 Mbps</td> </tr> <tr> <th>Audio codec</th> - <td>AAC-LC</th> - <td>AAC-LC</th> + <td>AAC-LC</td> + <td>AAC-LC</td> + <td>AAC-LC</td> </tr> <tr> <th>Audio channels</th> - <td>1 (mono)</th> - <td>2 (stereo)</th> + <td>1 (mono)</td> + <td>2 (stereo)</td> + <td>2 (stereo)</td> </tr> <tr> <th>Audio bitrate</th> - <td>24 Kbps</th> - <td>128 Kbps</th> + <td>24 Kbps</td> + <td>128 Kbps</td> + <td>192 Kbps</td> </tr> </tbody> </table> @@ -274,7 +322,8 @@ no dither applied for 24-bit. <p style="margin-top: 2em">For video content that is streamed over HTTP or RTSP, there are additional requirements:</p> <ul> - <li>For 3GPP and MPEG-4 containers, the <code>moov</code> atom must precede any <code>mdat</code> atoms.</li> + <li>For 3GPP and MPEG-4 containers, the <code>moov</code> atom must precede any <code>mdat</code> atoms, but must succeed the + <code>ftyp</code> atom.</li> <li>For 3GPP, MPEG-4, and WebM containers, audio and video samples corresponding to the same time offset may be no more than 500 KB apart. To minimize this audio/video drift, consider interleaving audio and video in smaller chunk sizes.</li> </ul> diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 9c3a0bea18e8..464430bb0bd9 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -222,8 +222,7 @@ <li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html"><receiver></a></li> <li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html"><service></a></li> <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-gl-texture-element.html"><supports-gl-texture></a></li> - <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html"><supports-screens></a> - <span class="new">updated</span></li> <!-- ##api level 4## --> + <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html"><supports-screens></a></li><!-- ##api level 4## --> <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html"><uses-configuration></a></li> <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-feature-element.html"><uses-feature></a></li> <!-- ##api level 4## --> <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-library-element.html"><uses-library></a></li> @@ -244,7 +243,7 @@ </a></li> <li><a href="<?cs var:toroot ?>guide/topics/graphics/opengl.html"> <span class="en">3D with OpenGL</span> - </a><span class="new">updated</span></li> + </a></li> <li><a href="<?cs var:toroot ?>guide/topics/graphics/animation.html"> <span class="en">Property Animation</span> </a></li> @@ -271,7 +270,7 @@ <li><a href="<?cs var:toroot ?>guide/topics/media/index.html"> <span class="en">Media</span> - </a><span class="new">updated</span></li> + </a></li> <li> <a href="<?cs var:toroot ?>guide/topics/clipboard/copy-paste.html"> <span class="en">Copy and Paste</span> @@ -408,7 +407,6 @@ </li> <li><a href="<?cs var:toroot ?>guide/market/publishing/multiple-apks.html"> <span class="en">Multiple APK Support</span></a> - <span class="new">new!</span> </li> </ul> </li> @@ -569,7 +567,7 @@ </a></div> <ul> <li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html">adb</a></li> - <li><a href="<?cs var:toroot ?>guide/developing/tools/adt.html">ADT</a> <span class="new">new!</span></li> + <li><a href="<?cs var:toroot ?>guide/developing/tools/adt.html">ADT</a></li> <li><a href="<?cs var:toroot ?>guide/developing/tools/android.html">android</a></li> <li><a href="<?cs var:toroot ?>guide/developing/tools/bmgr.html">bmgr</a> <li><a href="<?cs var:toroot ?>guide/developing/tools/dmtracedump.html">dmtracedump</a></li> @@ -672,14 +670,14 @@ <li class="toggle-list"> <div><a href="<?cs var:toroot ?>guide/practices/screens_support.html"> <span class="en">Supporting Multiple Screens</span> - </a> <span class="new">updated</span></div> + </a></div> <ul> <li><a href="<?cs var:toroot ?>guide/practices/screens-distribution.html"> <span class="en">Distributing to Specific Screens</span> </a></li> <li><a href="<?cs var:toroot ?>guide/practices/screen-compat-mode.html"> <span class="en">Screen Compatibility Mode</span> - </a> <span class="new">new!</span></li> + </a></li> <li><a href="<?cs var:toroot ?>guide/practices/screens-support-1.5.html"> <span class="en">Strategies for Android 1.5</span> </a></li> @@ -719,7 +717,7 @@ </ul> </li> <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/widget_design.html"> - <span class="en">App Widget Design</span> + <span class="en">App Widget Design <span class="new">updated</span></span> </a></li> <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/activity_task_design.html"> <span class="en">Activity and Task Design</span> @@ -737,11 +735,11 @@ <li class="toggle-list"> <div><a href="<?cs var:toroot ?>guide/practices/design/performance.html"> <span class="en">Designing for Performance</span> - </a> <span class="new-child">new!</span></div> + </a></div> <ul> <li><a href="<?cs var:toroot ?>guide/practices/design/jni.html"> <span class="en">JNI Tips</span> - </a> <span class="new">new!</span></li> + </a></li> </ul> </li> <li><a href="<?cs var:toroot ?>guide/practices/design/responsiveness.html"> @@ -793,7 +791,7 @@ <span class="en">App Install Location</span> </a></li> <li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html"> - <span class="en">Supported Media Formats</span> + <span class="en">Supported Media Formats <span class="new">updated</span></span> </a></li> <li><a href="<?cs var:toroot ?>guide/appendix/g-app-intents.html"> <span class="en">Intents List: Google Apps</span> diff --git a/docs/html/guide/practices/design/jni.jd b/docs/html/guide/practices/design/jni.jd index 6e984b00a881..9980efdf0c3f 100644 --- a/docs/html/guide/practices/design/jni.jd +++ b/docs/html/guide/practices/design/jni.jd @@ -26,9 +26,9 @@ page.title=JNI Tips </div> </div> -<p>JNI is the Java Native Interface. It defines a way for code written in the -Java programming language to interact with native -code: functions written in C/C++. It's VM-neutral, has support for loading code from +<p>JNI is the Java Native Interface. It defines a way for managed code +(written in the Java programming language) to interact with native +code (written in C/C++). It's vendor-neutral, has support for loading code from dynamic shared libraries, and while cumbersome at times is reasonably efficient.</p> <p>You really should read through the @@ -46,13 +46,13 @@ There's a more detailed <a href="http://java.sun.com/docs/books/jni/html/jniTOC. pointers to pointers to function tables. (In the C++ version, they're classes with a pointer to a function table and a member function for each JNI function that indirects through the table.) The JavaVM provides the "invocation interface" functions, -which allow you to create and destroy the VM. In theory you can have multiple VMs per process, -but Android's VM only allows one.</p> +which allow you to create and destroy a JavaVM. In theory you can have multiple JavaVMs per process, +but Android only allows one.</p> <p>The JNIEnv provides most of the JNI functions. Your native functions all receive a JNIEnv as the first argument.</p> -<p>On some VMs, the JNIEnv is used for thread-local storage. For this reason, <strong>you cannot share a JNIEnv between threads</strong>. +<p>The JNIEnv is used for thread-local storage. For this reason, <strong>you cannot share a JNIEnv between threads</strong>. If a piece of code has no other way to get its JNIEnv, you should share the JavaVM, and use <code>GetEnv</code> to discover the thread's JNIEnv. (Assuming it has one; see <code>AttachCurrentThread</code> below.)</p> @@ -66,23 +66,22 @@ that header refers to JNIEnv.)</p> <a name="threads" id="threads"></a> <h2>Threads</h2> -<p>All VM threads are Linux threads, scheduled by the kernel. They're usually -started using Java language features (notably <code>Thread.start</code>), -but they can also be created elsewhere and then attached to the VM. For +<p>All threads are Linux threads, scheduled by the kernel. They're usually +started from managed code (using <code>Thread.start</code>), +but they can also be created elsewhere and then attached to the JavaVM. For example, a thread started with <code>pthread_create</code> can be attached with the JNI <code>AttachCurrentThread</code> or <code>AttachCurrentThreadAsDaemon</code> functions. Until a thread is -attached to the VM, it has no JNIEnv, and -<strong>cannot make JNI calls</strong>.</p> +attached, it has no JNIEnv, and <strong>cannot make JNI calls</strong>.</p> -<p>Attaching a natively-created thread causes the VM to allocate and initialize -a <code>Thread</code> object, add it to the "main" <code>ThreadGroup</code>, -and add the thread to the set that is visible to the debugger. Calling -<code>AttachCurrentThread</code> on an already-attached thread is a no-op.</p> +<p>Attaching a natively-created thread causes a <code>java.lang.Thread</code> +object to be constructed and added to the "main" <code>ThreadGroup</code>, +making it visible to the debugger. Calling <code>AttachCurrentThread</code> +on an already-attached thread is a no-op.</p> -<p>The Dalvik VM does not suspend threads executing native code. If +<p>Android does not suspend threads executing native code. If garbage collection is in progress, or the debugger has issued a suspend -request, the VM will pause the thread the next time it makes a JNI call.</p> +request, Android will pause the thread the next time it makes a JNI call.</p> <p>Threads attached through JNI <strong>must call <code>DetachCurrentThread</code> before they exit</strong>. @@ -108,12 +107,12 @@ the argument.)</p> </ul> <p>Similarly, to call a method, you'd first get a class object reference and then a method ID. The IDs are often just -pointers to internal VM data structures. Looking them up may require several string +pointers to internal runtime data structures. Looking them up may require several string comparisons, but once you have them the actual call to get the field or invoke the method is very quick.</p> <p>If performance is important, it's useful to look the values up once and cache the results -in your native code. Because there is a limit of one VM per process, it's reasonable +in your native code. Because there is a limit of one JavaVM per process, it's reasonable to store this data in a static local structure.</p> <p>The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded. Classes @@ -145,13 +144,17 @@ then reloaded, it will be executed again.</p> <a name="local_and_global_references" id="local_and_global_references"></a> <h2>Local and Global References</h2> -<p>Every object that JNI returns is a "local reference". This means that it's valid for the +<p>Every argument passed to a native method, and almost every object returned +by a JNI function is a "local reference". This means that it's valid for the duration of the current native method in the current thread. -<strong>Even if the object itself continues to live on after the native method returns, the reference is not valid.</strong> -This applies to all sub-classes of <code>jobject</code>, including +<strong>Even if the object itself continues to live on after the native method +returns, the reference is not valid.</strong> +<p>This applies to all sub-classes of <code>jobject</code>, including <code>jclass</code>, <code>jstring</code>, and <code>jarray</code>. -(Dalvik VM will warn you about most reference mis-uses when extended JNI +(The runtime will warn you about most reference mis-uses when extended JNI checks are enabled.)</p> +<p>The only way to get non-local references is via the functions +<code>NewGlobalRef</code> and <code>NewWeakGlobalRef</code>. <p>If you want to hold on to a reference for a longer period, you must use a "global" reference. The <code>NewGlobalRef</code> function takes the @@ -159,7 +162,7 @@ local reference as an argument and returns a global one. The global reference is guaranteed to be valid until you call <code>DeleteGlobalRef</code>.</p> -<p>This pattern is commonly used when caching copies of class objects obtained +<p>This pattern is commonly used when caching a jclass returned from <code>FindClass</code>, e.g.:</p> <pre>jclass localClass = env->FindClass("MyClass"); jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));</pre> @@ -181,22 +184,25 @@ not use <code>jobject</code> values as keys.</p> <p>Programmers are required to "not excessively allocate" local references. In practical terms this means that if you're creating large numbers of local references, perhaps while running through an array of -Objects, you should free them manually with +objects, you should free them manually with <code>DeleteLocalRef</code> instead of letting JNI do it for you. The -VM is only required to reserve slots for +implementation is only required to reserve slots for 16 local references, so if you need more than that you should either delete as you go or use -<code>EnsureLocalCapacity</code> to reserve more.</p> +<code>EnsureLocalCapacity</code>/<code>PushLocalFrame</code> to reserve more.</p> -<p>Note that <code>jfieldID</code>s and <code>jmethodID</code>s are just integers, not object -references, and should not be passed to <code>NewGlobalRef</code>. The raw data +<p>Note that <code>jfieldID</code>s and <code>jmethodID</code>s are opaque +types, not object references, and should not be passed to +<code>NewGlobalRef</code>. The raw data pointers returned by functions like <code>GetStringUTFChars</code> -and <code>GetByteArrayElements</code> are also not objects.</p> +and <code>GetByteArrayElements</code> are also not objects. (They may be passed +between threads, and are valid until the matching Release call.)</p> <p>One unusual case deserves separate mention. If you attach a native -thread to the VM with <code>AttachCurrentThread</code>, the code you are running will -never "return" to the VM until the thread detaches from the VM. Any local -references you create will have to be deleted manually unless you're going -to detach the thread soon.</p> +thread with <code>AttachCurrentThread</code>, the code you are running will +never automatically free local references until the thread detaches. Any local +references you create will have to be deleted manually. In general, any native +code that creates local references in a loop probably needs to do some manual +deletion.</p> <a name="UTF_8_and_UTF_16_strings" id="UTF_8_and_UTF_16_strings"></a> <h2>UTF-8 and UTF-16 Strings</h2> @@ -205,14 +211,15 @@ to detach the thread soon.</p> modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00. The nice thing about this is that you can count on having C-style zero-terminated strings, suitable for use with standard libc string functions. The down side is that you cannot pass -arbitrary UTF-8 data into the VM and expect it to work correctly.</p> +arbitrary UTF-8 data to JNI and expect it to work correctly.</p> -<p>It's usually best to operate with UTF-16 strings. With Android's current VMs, the -<code>GetStringChars</code> method -does not require a copy, whereas <code>GetStringUTFChars</code> requires a malloc and a UTF conversion. Note that +<p>If possible, it's usually faster to operate with UTF-16 strings. Android +currently does not require a copy in <code>GetStringChars</code>, whereas +<code>GetStringUTFChars</code> requires an allocation and a conversion to +UTF-8. Note that <strong>UTF-16 strings are not zero-terminated</strong>, and \u0000 is allowed, so you need to hang on to the string length as well as -the string pointer.</p> +the jchar pointer.</p> <p><strong>Don't forget to <code>Release</code> the strings you <code>Get</code></strong>. The string functions return <code>jchar*</code> or <code>jbyte*</code>, which @@ -237,9 +244,8 @@ While arrays of objects must be accessed one entry at a time, arrays of primitives can be read and written directly as if they were declared in C.</p> <p>To make the interface as efficient as possible without constraining -the VM implementation, -the <code>Get<PrimitiveType>ArrayElements</code> family of calls -allows the VM to either return a pointer to the actual elements, or +the VM implementation, the <code>Get<PrimitiveType>ArrayElements</code> +family of calls allows the runtime to either return a pointer to the actual elements, or allocate some memory and make a copy. Either way, the raw pointer returned is guaranteed to be valid until the corresponding <code>Release</code> call is issued (which implies that, if the data wasn't copied, the array object @@ -253,7 +259,7 @@ non-NULL pointer for the <code>isCopy</code> argument. This is rarely useful.</p> <p>The <code>Release</code> call takes a <code>mode</code> argument that can -have one of three values. The actions performed by the VM depend upon +have one of three values. The actions performed by the runtime depend upon whether it returned a pointer to the actual data or a copy of it:</p> <ul> @@ -312,8 +318,9 @@ to do is copy data in or out. Consider the following:</p> }</pre> <p>This grabs the array, copies the first <code>len</code> byte -elements out of it, and then releases the array. Depending upon the VM -policies the <code>Get</code> call will either pin or copy the array contents. +elements out of it, and then releases the array. Depending upon the +implementation, the <code>Get</code> call will either pin or copy the array +contents. The code copies the data (for perhaps a second time), then calls <code>Release</code>; in this case <code>JNI_ABORT</code> ensures there's no chance of a third copy.</p> @@ -335,7 +342,7 @@ to copy data into an array, and <code>GetStringRegion</code> or <a name="exceptions" id="exceptions"></a> -<h2>Exception</h2> +<h2>Exceptions</h2> <p><strong>You must not call most JNI functions while an exception is pending.</strong> Your code is expected to notice the exception (via the function's return value, @@ -369,11 +376,11 @@ you call a method (using a function like <code>CallObjectMethod</code>), you must always check for an exception, because the return value is not going to be valid if an exception was thrown.</p> -<p>Note that exceptions thrown by interpreted code do not "leap over" native code, -and C++ exceptions thrown by native code are not handled by Dalvik. +<p>Note that exceptions thrown by interpreted code do not unwind native stack +frames, and Android does not yet support C++ exceptions. The JNI <code>Throw</code> and <code>ThrowNew</code> instructions just -set an exception pointer in the current thread. Upon returning to the VM from -native code, the exception will be noted and handled appropriately.</p> +set an exception pointer in the current thread. Upon returning to managed +from native code, the exception will be noted and handled appropriately.</p> <p>Native code can "catch" an exception by calling <code>ExceptionCheck</code> or <code>ExceptionOccurred</code>, and clear it with @@ -476,23 +483,19 @@ written in C++:</p> shared library. For Android apps, you may find it useful to get the full path to the application's private data storage area from the context object.</p> -<p>This is the recommended approach, but not the only approach. The VM does -not require explicit registration, nor that you provide a +<p>This is the recommended approach, but not the only approach. Explicit +registration is not required, nor is it necessary that you provide a <code>JNI_OnLoad</code> function. You can instead use "discovery" of native methods that are named in a -specific way (see <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615"> - the JNI spec</a> for details), though this is less desirable. -It requires more space in the shared object symbol table, -loading is slower because it requires string searches through all of the -loaded shared libraries, and if a method signature is wrong you won't know +specific way (see <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615">the JNI spec</a> for details), though this is less desirable because if a method signature is wrong you won't know about it until the first time the method is actually used.</p> <p>One other note about <code>JNI_OnLoad</code>: any <code>FindClass</code> calls you make from there will happen in the context of the class loader that was used to load the shared library. Normally <code>FindClass</code> uses the loader associated with the method at the top of the interpreted -stack, or if there isn't one (because the thread was just attached to -the VM) it uses the "system" class loader. This makes +stack, or if there isn't one (because the thread was just attached) it uses +the "system" class loader. This makes <code>JNI_OnLoad</code> a convenient place to look up and cache class object references.</p> @@ -515,10 +518,9 @@ that use 64-bit pointers, <strong>you need to stash your native pointers in a <p>All JNI 1.6 features are supported, with the following exceptions:</p> <ul> - <li><code>DefineClass</code> is not implemented. Dalvik does not use + <li><code>DefineClass</code> is not implemented. Android does not use Java bytecodes or class files, so passing in binary class data - doesn't work. Translation facilities may be added in a future - version of the VM.</li> + doesn't work.</li> <li>"Weak global" references are implemented, but may only be passed to <code>NewLocalRef</code>, <code>NewGlobalRef</code>, and <code>DeleteWeakGlobalRef</code>. (The spec strongly encourages @@ -536,12 +538,16 @@ that use 64-bit pointers, <strong>you need to stash your native pointers in a around this requires using explicit registration or moving the native methods out of inner classes. <li>Until Android 2.0 (Eclair), it was not possible to use a <code>pthread_key_create</code> - destructor function to avoid the VM's "thread must be detached before - exit" check. (The VM also uses a pthread key destructor function, + destructor function to avoid the "thread must be detached before + exit" check. (The runtime also uses a pthread key destructor function, so it'd be a race to see which gets called first.) <li>Until Android 2.2 (Froyo), weak global references were not implemented. - Older VMs will vigorously reject attempts to use them. You can use + Older versions will vigorously reject attempts to use them. You can use the Android platform version constants to test for support. + <li>Until Android 4.0 (Ice Cream Sandwich), JNI local references were + actually direct pointers. Ice Cream Sandwich added the indirection + necessary to support better garbage collectors, but this means that lots + of JNI bugs are undetectable on older releases. </ul> @@ -572,8 +578,8 @@ the details of the failure can be found in the exception's detail message.</p> <p>In logcat, you'll see:</p> <pre>W/dalvikvm( 880): No implementation found for native LFoo;.myfunc ()V</pre> -<p>This means that the VM tried to find a matching method but was unsuccessful. -Some common reasons for this are:</p> +<p>This means that the runtime tried to find a matching method but was +unsuccessful. Some common reasons for this are:</p> <ul> <li>The library isn't getting loaded. Check the logcat output for messages about library loading. @@ -581,10 +587,15 @@ Some common reasons for this are:</p> is commonly caused by: <ul> <li>For lazy method lookup, failing to declare C++ functions - with <code>extern "C"</code>. You can use <code>arm-eabi-nm</code> + with <code>extern "C"</code> and appropriate + visibility (<code>JNIEXPORT</code>). Note that prior to Ice Cream + Sandwich, the JNIEXPORT macro was incorrect, so using a new GCC with + an old <code>jni.h</code> won't work. + You can use <code>arm-eabi-nm</code> to see the symbols as they appear in the library; if they look mangled (something like <code>_Z15Java_Foo_myfuncP7_JNIEnvP7_jclass</code> - rather than <code>Java_Foo_myfunc</code>) then you need to + rather than <code>Java_Foo_myfunc</code>), or if the symbol type is + a lowercase 't' rather than an uppercase 'T', then you need to adjust the declaration. <li>For explicit registration, minor errors when entering the method signature. Make sure that what you're passing to the @@ -612,7 +623,7 @@ must also wrap the class with 'L' and ';', so a one-dimensional array of <p>If the class name looks right, you could be running into a class loader issue. <code>FindClass</code> wants to start the class search in the -class loader associated with your code. It examines the VM call stack, +class loader associated with your code. It examines the call stack, which will look something like: <pre> Foo.myfunc(Native Method) Foo.main(Foo.java:10) @@ -623,14 +634,14 @@ finds the <code>ClassLoader</code> object associated with the <code>Foo</code> class and uses that.</p> <p>This usually does what you want. You can get into trouble if you -create a thread outside the VM (perhaps by calling <code>pthread_create</code> -and then attaching it to the VM with <code>AttachCurrentThread</code>). +create a thread yourself (perhaps by calling <code>pthread_create</code> +and then attaching it with <code>AttachCurrentThread</code>). Now the stack trace looks like this:</p> <pre> dalvik.system.NativeStart.run(Native Method)</pre> <p>The topmost method is <code>NativeStart.run</code>, which isn't part of your application. If you call <code>FindClass</code> from this thread, the -VM will start in the "system" class loader instead of the one associated +JavaVM will start in the "system" class loader instead of the one associated with your application, so attempts to find app-specific classes will fail.</p> <p>There are a few ways to work around this:</p> @@ -656,12 +667,12 @@ with your application, so attempts to find app-specific classes will fail.</p> <h2>FAQ: How do I share raw data with native code?</h2> <p>You may find yourself in a situation where you need to access a large -buffer of raw data from code written in Java and C/C++. Common examples +buffer of raw data from both managed and native code. Common examples include manipulation of bitmaps or sound samples. There are two basic approaches.</p> <p>You can store the data in a <code>byte[]</code>. This allows very fast -access from code written in Java. On the native side, however, you're +access from managed code. On the native side, however, you're not guaranteed to be able to access the data without having to copy it. In some implementations, <code>GetByteArrayElements</code> and <code>GetPrimitiveArrayCritical</code> will return actual pointers to the @@ -674,8 +685,8 @@ the JNI <code>NewDirectByteBuffer</code> function. Unlike regular byte buffers, the storage is not allocated on the managed heap, and can always be accessed directly from native code (get the address with <code>GetDirectBufferAddress</code>). Depending on how direct -byte buffer access is implemented in the VM, accessing the data from code -written in Java can be very slow.</p> +byte buffer access is implemented, accessing the data from managed code +can be very slow.</p> <p>The choice of which to use depends on two factors:</p> <ol> @@ -688,5 +699,4 @@ written in Java can be very slow.</p> </ol> <p>If there's no clear winner, use a direct byte buffer. Support for them -is built directly into JNI, and access to them from code written in -Java can be made faster with VM improvements.</p> +is built directly into JNI, and performance should improve in future releases.</p> diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd index 49aa4981c581..de20e007f393 100644 --- a/docs/html/guide/practices/ui_guidelines/widget_design.jd +++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd @@ -1,4 +1,4 @@ -page.title=Widget Design Guidelines +page.title=App Widget Design Guidelines parent.title=UI Guidelines parent.link=index.html @jd:body @@ -9,268 +9,322 @@ parent.link=index.html <h2>Quickview</h2> <ul> -<li>Widgets have six standard sizes on the Home screen</li> -<li>Widgets have standards for size, frames, shadows, and file format, which you can copy</li> -<li>A few tricks make it easier to design widgets that fit graphically on the Home screen</li> + <li>App Widget layouts should be flexible, resizing to fit their parent container</li> + <li>As of Android 3.0, app widgets can depict collections of items and provide a representative + preview image for the widget gallery</li> + <li>As of Android 3.1, app widgets can be resizable horizontally and/or vertically</li> + <li>As of Android 4.0, app widgets have margins automatically applied</li> </ul> <h2>In this document</h2> <ol> -<li><a href="#anatomy">Standard widget anatomy</a></li> -<li><a href="#design">Designing a widget</a></li> -<li><a href="#sizes">Standard widget sizes</a></li> -<li><a href="#frames">Standard widget frames</a></li> -<li><a href="#shadows">Standard widget shadows</a></li> -<li><a href="#tricks">Widget graphics tips and tricks</a></li> -<li><a href="#file">Widget graphics file format</a></li> +<li><a href="#anatomy">Standard Widget Anatomy</a></li> +<li><a href="#design">Designing Widget Layouts and Background Graphics</a></li> +<li><a href="#templates">Using the App Widget Templates Pack</a></li> +</ol> + +<h2>Downloads</h2> + +<ol> +<li><a href="{@docRoot}shareables/app_widget_templates-v4.0.zip">App Widget Templates Pack, + v4.0 »</a></li> </ol> <h2>See also</h2> <ol> <li><a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a></li> -<li><a href="http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html">AppWidgets blog post</a></li> +<li> + <a href="http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html"> + AppWidgets blog post</a></li> </ol> </div> </div> -<p>Widgets are a feature introduced in Android 1.5. A widget displays an -application's most important or timely information at a glance, on a user's Home -screen. The standard Android system image includes several examples of widgets, -including widgets for Analog Clock, Music, and other applications.</p> - -<p>Users pick the widgets they want to display on their Home screens by touching -& holding an empty area of the Home screen, selecting Widgets from the menu, -and then selecting the widget they want.</p> - -<p><img src="{@docRoot}images/widget_design/widget_examples.png" alt="Example -Widgets"></p> - -<p>This document describes how to design a widget so it fits graphically with -other widgets and with the other elements of the Android Home screen. It also -describes some standards for widget artwork and some widget graphics tips and -tricks from the Android team.<p> - -<p>For information about developing widgets, see the <a -href="{@docRoot}guide/topics/appwidgets/index.html">AppWidgets</a> section of -the <em>Developer's Guide</em> and the <a -href="http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html">AppWidgets</a> blog post.</p> - - -<h2 id="anatomy">Standard widget anatomy</h2> +<p>App widgets (sometimes just "widgets") are a feature introduced in Android 1.5 and vastly +improved in Android 3.0 and 3.1. A widget can display an application's most timely or otherwise +relevant information at a glance, on a user's Home screen. The standard Android system image +includes several widgets, including a widget for the Analog Clock, Music, and other +applications.</p> -<p>Typical Android widgets have three main components: A bounding box, a frame, -and the widget's graphical controls and other elements. Well-designed widgets -leave some padding between the edges of the bounding box and the frame, and -between the inner edges of the frame and the widget's controls. Widgets designed -to fit visually with other widgets on the Home screen take cues from the other -elements on the Home screen for alignment; they also use standard shading -effects. All of these details are described in this document. -<p><strong>Standard Widget Sizes in Portrait Orientation</strong><br/> -<img src="{@docRoot}images/widget_design/widget_sizes_portrait.png" -alt="Standard Widget Sizes in Portrait Orientation"></p> +<img src="{@docRoot}images/widget_design/widget_examples.png" + alt="Example app widgets in Android 4.0" id="widget_examples"> -<p> </p> +<p class="img-caption"><strong>Figure 1.</strong> Example app widgets in Android 4.0.</p> -<p><strong>Standard Widget Sizes in Landscape Orientation</strong><br/> -<img src="{@docRoot}images/widget_design/widget_sizes_landscape.png" -alt="Standard Widget Sizes in Landscape Orientation"></p> - -<h2 id="design">Designing a widget</h2> +<p>This document describes how to design a widget so that it fits graphically with other widgets and +with the other elements of the Android Home screen such as launcher icons and shortcuts. It also +describes some standards for widget artwork and some widget graphics tips and tricks.<p> -<ol> -<li><strong>Select a bounding box size for your widget.</strong></li> +<p>For information about developing widgets, see the <a +href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> section of the <em>Developer's +Guide</em>.</p> + + +<h2 id="anatomy">Standard Widget Anatomy</h2> + +<p>Typical Android app widgets have three main components: A bounding box, a frame, and the widget's +graphical controls and other elements. App widgets can contain a subset of the View widgets in +Android; supported controls include text labels, buttons, and images. For a full list of available +Views, see the <a href="{@docRoot}guide/topics/appwidgets/index.html#CreatingLayout">Creating the +App Widget Layout</a> section in the <em>Developer's Guide</em>. Well-designed widgets leave some +margins between the edges of the bounding box and the frame, and padding between the inner edges of +the frame and the widget's controls.</p> + + +<img src="{@docRoot}images/widget_design/widget_terms.png" + alt="Widgets generally have margins and padding between bounding box, frame, and controls" + id="widget_terms"> + +<p class="img-caption"><strong>Figure 2.</strong> Widgets generally have margins between the +bounding box and frame, and padding between the frame and widget controls.</p> + + +<p class="note"><strong>Note: </strong> As of Android 4.0, app widgets are automatically given +margins between the widget frame and the app widget's bounding box to provide better alignment with +other widgets and icons on the user's home screen. To take advantage of this strongly recommended +behavior, set your application's <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">targetSdkVersion</a> to 14 or +greater.</p> + +<p>Widgets designed to fit visually with other widgets on the Home screen take cues from the other +elements on the Home screen for alignment; they also use standard shading effects. All of these +details are described in this document.</p> + + +<h3 id="anatomy_determining_size">Determining a size for your widget</h3> + +<p>Each widget must define a <code>minWidth</code> and <code>minHeight</code>, indicating the +minimum amount of space it should consume by default. When users add a widget to their Home screen, +it will generally occupy more than the minimum width and height you specify. Android Home screens +offer users a grid of available spaces into which they can place widgets and icons. This grid can +vary by device; for example, many handsets offer a 4x4 grid, and tablets can offer a larger, 8x7 +grid. <strong>When your widget is added, it will be stretched to occupy the minimum number of cells, +horizontally and vertically, required to satisfy its <code>minWidth</code> and +<code>minHeight</code> constraints.</strong> As we discuss in <a href="#design">Designing Widget +Layouts and Background Graphics</a> below, using nine-patch backgrounds and flexible layouts for app +widgets will allow your widget to gracefully adapt to the device's Home screen grid and remain +usable and aesthetically awesome.</p> + +<p>While the width and height of a cell—as well as the amount of automatic margins applied to +widgets—may vary across devices, you can use the table below to roughly estimate your widget's +minimum dimensions, given the desired number of occupied grid cells:</p> + +<table id="cellstable"> + <thead> + <tr> + <th># of Cells<br><small style="font-weight:normal">(Columns or Rows)</small></th> + <th>Available Size (dp)<br><small style="font-weight:normal">(<code>minWidth</code> or + <code>minHeight</code>)</small></th> + </tr> + </thead> + <tbody> + <tr> + <td>1</td> + <td>40dp</td> + </tr> + <tr> + <td>2</td> + <td>110dp</td> + </tr> + <tr> + <td>3</td> + <td>180dp</td> + </tr> + <tr> + <td>4</td> + <td>250dp</td> + </tr> + <tr> + <td>…</td> + <td>…</td> + </tr> + <tr> + <td><em>n</em></td> + <td>70 × <em>n</em> − 30</td> + </tr> + </tbody> +</table> -<p>The most effective widgets display your application's most useful or timely -data in the smallest widget size. Users will weigh the usefulness or your widget -against the portion of the Home screen it covers, so the smaller the better.</p> +<p>It is a good practice to be conservative with <code>minWidth</code> and <code>minHeight</code>, +specifying the minimum size that renders the widget in a good default state. For an example of how +to provide a <code>minWidth</code> and <code>minHeight</code>, suppose you have a music player +widget that shows the currently playing song artist and title (vertically stacked), a +<strong>Play</strong> button, and a <strong>Next</strong> button:</p> -<p>All widgets must fit within the bounding box of one of the six supported -widget sizes, or better yet, within a pair of portrait and landscape orientation -sizes, so your widget looks good when the user switches screen -orientations.</p> -<p><a href="#sizes">Standard widget sizes</a> illustrates the bounding -dimensions of the six widget sizes (three in portrait and three in landscape -orientation).</p> +<img src="{@docRoot}images/widget_design/music_example.png" + alt="An example music player widget" id="music_example"> +<p class="img-caption"><strong>Figure 3.</strong> An example music player widget.</p> -<li><strong>Select a matching frame.</strong></li> -<p><a href="#frames">Standard widget frames</a> illustrates the standard frames -for the six widget sizes, with links so you can download copies for your own -use. You don't have to use these frames for your widget, but if you do, your -widgets are more likely to fit visually with other widgets.</p> +<p>Your minimum height should be the height of your two TextViews for the artist and title, plus +some text margins. Your minimum width should be the minimum usable widths of the +<strong>Play</strong> and <strong>Next</strong> buttons, plus the minimum text width (say, the width +of 10 characters), plus any horizontal text margins.</p> -<li><strong>Apply standard shadow effect to your graphics.</strong></li> -<p>Again, you don't have to use this effect, but <a href="#shadows">Standard -widget shadows</a> shows the Photoshop settings used for standard widgets.</p> +<img src="{@docRoot}images/widget_design/music_example_redline.png" +alt="Example sizes and margins for minimum width/height calculations" id="music_example_redline"> -<li><strong>If your widget includes buttons, draw them in three states -(default, pressed, and selected).</strong></li> +<p class="img-caption"><strong>Figure 4.</strong> Example sizes and margins for +<code>minWidth</code>/<code>minHeight</code> calculations. We chose 144dp as an example good minimum +width for the text labels.</p> -<p>You can <a -href="{@docRoot}images/widget_design/Music_widget_button_states.psd">download a -Photoshop file that contains the three states of the Play button</a>, taken from -the Music widget, to analyze the Photoshop settings used for the three standard -button effects.</p> -<p><a href="{@docRoot}images/widget_design/Music_widget_button_states.psd"> <img -src="{@docRoot}images/widget_design/buttons.png" alt="Click to download -Photoshop template"></a></p> - -<li><strong>Finish drawing your artwork and then scale and align it to -fit.</strong></li> +<p>Example calculations are below:</p> -<p><a href="#tricks">Widget alignment tips and tricks</a> describes some -techniques for aligning your widget's graphics inside the standard frames, along -with a few other widget graphics tricks.</p> +<ul> + <li><code>minWidth</code> = 144dp + (2 × 8dp) + (2 × 56dp) = + <strong>272dp</strong></li> + <li><code>minHeight</code> = 48dp + (2 × 4dp) = <strong>56dp</strong></li> +</ul> -<li><strong>Save your widget with the correct graphics file -settings.</strong></li> +<p>If there is any inherent content padding in your widget background nine-patch, you should add to +<code>minWidth</code> and <code>minHeight</code> accordingly.</p> -<p><a href="#file">Windows graphics file format</a> describes the correct -settings for your widget graphics files.</p> -</ol> +<h3 id="anatomy_resizable_widgets">Resizable widgets</h3> +<p>Widgets can be resized horizontally and/or vertically as of Android 3.1, meaning that +<code>minWidth</code> and <code>minHeight</code> effectively become the <em>default</em> size for +the widget. You can specify the minimum widget size using <code>minResizeWidth</code> and +<code>minResizeHeight</code>; these values should specify the size below which the widget would be +illegible or otherwise unusable.</p> -<h2 id="sizes">Standard widget sizes</h2> +<p>This is generally a preferred feature for collection widgets such as those based on {@link +android.widget.ListView} or {@link android.widget.GridView}.</p> -<p>There are six standard widget sizes, based on a Home screen grid of 4 x 4 -(portrait) or 4 x 4 (landscape) cells. These dimensions are the bounding boxes -for the six standard widget sizes. The contents of typical widgets don't draw to -the edge of these dimensions, but fit inside a frame withing the bounding box, -as described in <a href="#design">Designing a widget</a>.</p> -<p>In portrait orientation, each cell is 80 pixels wide by 100 pixels tall (the -diagram shows a cell in portrait orientation). The three supported widget sizes -in portrait orientation are:<p> +<h3 id="anatomy_adding_margins">Adding margins to your app widget</h3> -<table> -<tr><th>Cells</th><th>Pixels</th></tr> -<tr><td>4 x 1</td><td>320 x 100</td></tr> -<tr><td>3 x 3</td><td>240 x 300</td></tr> -<tr><td>2 x 2</td><td>160 x 200</td></tr> -</table> +<p>As previously mentioned, Android 4.0 will automatically add small, standard margins to each edge +of widgets on the Home screen, for applications that specify a <code>targetSdkVersion</code> of 14 +or greater. This helps to visually balance the Home screen, and thus <strong>we recommend that you +do not add any extra margins outside of your app widget's background shape in Android +4.0</strong>.</p> -<p><img src="{@docRoot}images/widget_design/portrait_sizes.png" alt="Widget -dimensions in portrait orientation"></p> +<p>It's easy to write a single layout that has custom margins applied for earlier versions of the +platform, and has no extra margins for Android 4.0 and greater. See <a +href="{@docRoot}guide/topics/appwidgets/index.html#AddingMargins">Adding Margins to App Widgets</a> +in the <em>Developer's Guide</em> for information on how to achieve this with layout XML.</p> -<p>In landscape orientation, each cell is 106 pixels wide by 74 pixels tall. The -three supported widget sizes in landscape orientation are:</p> -<table> -<tr><th>Cells</th><th>Pixels</th></tr> -<tr><td>4 x 1</td><td>424 x 74</td></tr> -<tr><td>3 x 3</td><td>318 x 222</td></tr> -<tr><td>2 x 2</td><td>212 x 148</td></tr> -</table> +<h2 id="design">Designing Widget Layouts and Background Graphics</h2> -<p><img src="{@docRoot}images/widget_design/landscape_sizes.png" alt="Widget -dimensions in landscape orientation"></p> +<p>Most widgets will have a solid background rectangle or rounded rectangle shape. It is a best +practice to define this shape using nine patches; one for each screen density (see <a +href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> for details). +Nine-patches can be created with the <a +href="{@docRoot}guide/developing/tools/draw9patch.html">draw9patch</a> tool, or simply with a +graphics editing program such as Adobe® Photoshop. This will allow the widget background shape +to take up the entire available space. The nine-patch should be edge-to-edge with no transparent +pixels providing extra margins, save for perhaps a few border pixels for <strong>subtle</strong> +drop shadows or other subtle effects.</p> +<p class="note"><strong>Note: </strong> Just like with controls in activities, you should ensure +that interactive controls have distinct visual focused and pressed states using <a +href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state list +drawables</a>.</p> -<h2 id="frames">Standard widget frames</h2> -<p>For each of the six standard widget sizes there is a standard frame. You can -click the images of the frames in this section to download a Photoshop file for -that frame, which you can use for your own widgets.<p> +<img src="{@docRoot}images/ninepatch_raw.png" alt="Nine-patch border pixels" id="ninepatch_raw"> -<p><a href="{@docRoot}images/widget_design/4x1_Widget_Frame_Portrait.psd"> <img -src="{@docRoot}images/widget_design/4x1_Widget_Frame_Portrait.png" alt="Click to -download"></a><br>4x1_Widget_Frame_Portrait.psd</p> +<p class="img-caption"><strong>Figure 5.</strong> Nine-patch border pixels indicating stretchable +regions and content padding.</p> -<p><a href="{@docRoot}images/widget_design/3x3_Widget_Frame_Portrait.psd"> <img -src="{@docRoot}images/widget_design/3x3_Widget_Frame_Portrait.png" alt="Click to -download"></a><br>3x3_Widget_Frame_Portrait.psd</p> -<p><a href="{@docRoot}images/widget_design/2x2_Widget_Frame_Portrait.psd"> <img -src="{@docRoot}images/widget_design/2x2_Widget_Frame_Portrait.png" alt="Click to -download"></a><br>2x2_Widget_Frame_Portrait.psd</p> +<p>Some app widgets, such as those using a {@link android.widget.StackView}, have a transparent +background. For this case, each individual item in the StackView should use a nine-patch background +that is edge-to-edge with little or no border transparent pixels for margins.</p> -<p><a href="{@docRoot}images/widget_design/4x1_Widget_Frame_Landscape.psd"> <img -src="{@docRoot}images/widget_design/4x1_Widget_Frame_Landscape.png" alt="Click -to download"></a><br>4x1_Widget_Frame_Landscape.psd</p> +<p>For the contents of the widget, you should use flexible layouts such as {@link +android.widget.RelativeLayout}, {@link android.widget.LinearLayout}, or {@link +android.widget.FrameLayout}. Just as your activity layouts must adapt to different physical screen +sizes, widget layouts must adapt to different Home screen grid cell sizes.</p> -<p><a href="{@docRoot}images/widget_design/3x3_Widget_Frame_Landscape.psd"> <img -src="{@docRoot}images/widget_design/3x3_Widget_Frame_Landscape.png" alt="Click -to download"></a><br>3x3_Widget_Frame_Landscape.psd</p> +<p>Below is an example layout that a music widget showing text information and two buttons can use. +It builds upon the previous discussion of adding margins depending on OS version.</p> -<p><a href="{@docRoot}images/widget_design/2x2_Widget_Frame_Landscape.psd"> <img -src="{@docRoot}images/widget_design/2x2_Widget_Frame_Landscape.png" alt="Click -to download"></a><br>2x2_Widget_Frame_Landscape.psd</p> +<pre> +<FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="@dimen/widget_margin"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + android:background="@drawable/my_widget_background"> -<h2 id="shadows">Standard widget shadows</h2> + <TextView + android:id="@+id/song_info" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" /> -<p>You can apply a shadow effect to your widget's artwork, so it matches other -standard Android widgets, using the following settings in the Photoshop Layer -Style dialog box.</p> + <Button + android:id="@+id/play_button" + android:layout_width="@dimen/my_button_width" + android:layout_height="match_parent" /> -<p><img src="{@docRoot}images/widget_design/Layer_Style.png" alt="Layer Style -settings for standard shadows"></p> + <Button + android:id="@+id/skip_button" + android:layout_width="@dimen/my_button_width" + android:layout_height="match_parent" /> + </LinearLayout> +</FrameLayout> +</pre> +<p>If you now take a look at the example music widget from the previous section, you can begin to +use flexible layouts attributes like so:</p> -<h2 id="tricks">Widget graphics tips and tricks</h2> -<p>The Android team has developed a few tricks for aligning widget artwork -within standard widget bounding boxes and frames, so the widget aligns visually -with other widgets and the other elements of the Home screen, as well as other -techniques for creating widgets. +<img src="{@docRoot}images/widget_design/music_example_layouts.png" + alt="Excerpt flexible layouts and attributes for an example music widget" + id="music_example_layouts"> -<ul> +<p class="img-caption"><strong>Figure 6.</strong> Excerpt flexible layouts and attributes.</p> -<li>Use a screen shot from the Android SDK emulator to align both the shapes and -shadows of your widget controls with the Search widget and with other elements -on the Home screen.</li> -<p>Cut the widget artwork asset" based on the full size of a cell, including any -padding you want. (That is, for a 4 x 1 widget, cut the asset at 320 by 100 -pixels.)</p> +<p>When a user adds the widget to their home screen, on an example Android 4.0 device where each +grid cell is 80dp × 100dp in size and 16dp of margins are automatically applied on all sizes, +the widget will be stretched, like so:</p> -<p><img src="{@docRoot}images/widget_design/alignment.png" alt="Aligning widget -graphics" ></p> -<li>To reduce banding when exporting a widget, apply the following Photoshop Add -Noise setting to your graphic.</li> +<img src="{@docRoot}images/widget_design/music_example_stretched.png" + alt="Music widget sitting on an example 80dp x 100dp grid with 16dp of automatic margins + added by the system" id="music_example_stretched"> -<p><img src="{@docRoot}images/widget_design/Add_Noise.png" alt="Add Noise -settings for widget graphics" ></p> +<p class="img-caption"><strong>Figure 7.</strong> Music widget sitting on an example 80dp x 100dp +grid with 16dp of automatic margins added by the system.</p> -<li>Apply 9-patch techniques to shrink the graphic and set the padding of the -content area. (<a href="{@docRoot}guide/developing/tools/draw9patch.html">See -the detailed guide here.</a>)</li> -<p><strong>Note:</strong> The current Android widget templates were designed -using a custom gradient angle, which means the 9-patch techniques can't be used -to optimize the size of the asset. However, 9-patch techniques were used to set -the content area padding.</p> +<h2 id="templates">Using the App Widget Templates Pack</h2> -<li>In some cases, devices have low pixel depths that can cause visual banding -and dithering issues. To solve this, application developers should pass assets -through a "proxy" drawable defined as <code>XML:<nine-patch -android:src="@drawable/background" android:dither="true" /></code>. This -technique references the original artwork, in this case -<code>"background.9.png"</code>, and instructs the device to dither it as -needed.</li> - -</ul> +<p>When starting to design a new widget, or updating an existing widget, it's a good idea to first +look at the widget design templates below. The downloadable package below includes nine-patch +background graphics, XML, and source Adobe® Photoshop files for multiple screen densities, OS +version widget styles, and widget colors. The template package also contains graphics useful for +making your entire widget or parts of your widget (e.g. buttons) interactive.</p> -<h2 id="file">Widget graphics file format</h2> -<p>Save your widget artwork using the appropriate bounding box size in PNG-24 -format on a transparent background and in 8-bit color.</p> +<img src="{@docRoot}images/widget_design/widget_template_excerpts.png" + alt="Widget template excerpts" id="widget_template_excerpts"> -<p><img src="{@docRoot}images/widget_design/file_format.png" alt="Widget graphics file format" ></p> +<p class="img-caption"><strong>Figure 8.</strong> Excerpts from the App Widget Templates Pack +(medium-density, dark, Android 4.0/previous styles, default/focused/pressed states).</p> - +<p>You can obtain the latest App Widget Templates Pack archive using the link below:</p> +<p style="margin-left:2em"><a href="{@docRoot}shareables/app_widget_templates-v4.0.zip"> + Download the App Widget Templates Pack for Android 4.0 »</a></p> diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd index 78b5b511b603..22283cdc306b 100644 --- a/docs/html/guide/topics/appwidgets/index.jd +++ b/docs/html/guide/topics/appwidgets/index.jd @@ -327,6 +327,49 @@ following layout classes:</p> <p>Descendants of these classes are not supported.</p> +<h3 id="AddingMargins">Adding margins to App Widgets</h3> + +<p>Widgets should not generally extend to screen edges and should not visually be flush with other widgets, so you should add margins on all sides around your widget frame.</p> + +<p>As of Android 4.0, app widgets are automatically given padding between the widget frame and the app widget's bounding box to provide better alignment with other widgets and icons on the user's home screen. To take advantage of this strongly recommended behavior, set your application's <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">targetSdkVersion</a> to 14 or greater.</p> + +<p>It's easy to write a single layout that has custom margins applied for earlier versions of the platform, and has no extra margins for Android 4.0 and greater:</p> + +<ol> + <li>Set your application's <code>targetSdkVersion</code> to 14 or greater.</li> + <li>Create a layout such as the one below, that references a <a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">dimension resource</a> for its margins: + +<pre> +<FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + <strong>android:layout_margin="@dimen/widget_margin"></strong> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + android:background="@drawable/my_widget_background"> + … + </LinearLayout> + +</FrameLayout> +</pre> + + </li> + <li>Create two dimensions resources, one in <code>res/values/</code> to provide the pre-Android 4.0 custom margins, and one in <code>res/values-v14/</code> to provide no extra padding for Android 4.0 widgets: + + <p><strong>res/values/dimens.xml</strong>:<br> + <pre><dimen name="widget_margin">15dp</dimen></pre></p> + + <p><strong>res/values-v14/dimens.xml</strong>:<br> + <pre><dimen name="widget_margin">0dp</dimen></pre></p> + </li> +</ol> + +<p>Another option is to simply build extra margins into your <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">nine-patch</a> background assets by default, and provide different nine-patches with no margins for API level 14 or later.</p> + + <h2 id="AppWidgetProvider">Using the AppWidgetProvider Class</h2> <div class="sidebox-wrapper"> diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd index abc945ab6c36..f12c5eefc950 100644 --- a/docs/html/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html/guide/topics/ui/notifiers/notifications.jd @@ -12,7 +12,7 @@ without interupting their current activity</li> <li>You can attach an intent to your notification that the system will initiate when the user clicks it</li> </ul> - + <h2>In this document</h2> <ol> <li><a href="#Basics">The Basics</a></li> @@ -26,7 +26,7 @@ user clicks it</li> <li><a href="#More">More features</a></li> </ol> </li> - <li><a href="#CustomExpandedView">Creating a Custom Expanded View</a></li> + <li><a href="#CustomExpandedView">Creating a Custom Notification Layout</a></li> </ol> <h2>Key classes</h2> <ol> @@ -36,57 +36,63 @@ user clicks it</li> </div> </div> -<p>A status bar notification adds an icon to the system's status bar -(with an optional ticker-text message) and an expanded message in the "Notifications" window. -When the user selects the expanded message, Android fires an -{@link android.content.Intent} that is defined by the notification (usually to launch an -{@link android.app.Activity}). +<p>A status bar notification adds an icon to the system's status bar +(with an optional ticker-text message) and a notification message in the notifications window. +When the user selects the notification, Android fires an +{@link android.content.Intent} that is defined by the {@link android.app.Notification} (usually to +launch an {@link android.app.Activity}). You can also configure the notification to alert the user with a sound, a vibration, and flashing lights on the device.</p> <p>A status bar notification should be used for any case in -which a background Service needs to alert the user about an event that requires a response. A background Service -<strong>should never</strong> launch an Activity on its own in order to receive user interaction. -The Service should instead create a status bar notification that will launch the Activity +which a background service needs to alert the user about an event that requires a response. A +background service +<strong>should never</strong> launch an activity on its own in order to receive user interaction. +The service should instead create a status bar notification that will launch the activity when selected by the user.</p> -<p>The screenshot below shows the status bar with a notification icon on the left side.</p> +<p>Figure 1 shows the status bar with a notification icon on the left side.</p> <img src="{@docRoot}images/status_bar.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> Status bar with a notification.</p> + +<p>Figure 2 shows the notification's message in the notifications window.</p> -<p>The next screenshot shows the notification's expanded message in the "Notifications" window. -The user can reveal the Notifications window by pulling down the status bar -(or selecting <em>Notifications</em> from the Home options menu).</p> <img src="{@docRoot}images/notifications_window.png" alt="" /> +<p class="img-caption"><strong>Figure 2.</strong> The notifications window.</p> <h2 id="Basics">The Basics</h2> -<p>An {@link android.app.Activity} or {@link android.app.Service} can initiate a status bar -notification. Because an Activity can perform actions only while it is -active and in focus, you should create your status bar notifications from a -Service. This way, the notification can be created from the background, +<p>An {@link android.app.Activity} or {@link android.app.Service} can initiate a status bar +notification. Because an activity can perform actions only while it is +running in the foreground and its window has focus, you will usually create status bar notifications +from a +service. This way, the notification can be created from the background, while the user is using another application or while the device is asleep. To create a notification, you must use two classes: {@link android.app.Notification} and {@link android.app.NotificationManager}.</p> -<p>Use an instance of the {@link android.app.Notification} class to define the properties of your -status bar notification, such as the status bar icon, the expanded message, and extra settings such -as a sound to play. The {@link android.app.NotificationManager} is an Android system service that -executes and manages all Notifications. You do not instantiate the NotificationManager. In order -to give it your Notification, you must retrieve a reference to the NotificationManager with -{@link android.app.Activity#getSystemService(String) getSystemService()} and -then, when you want to notify the user, pass it your Notification object with +<p>Use an instance of the {@link android.app.Notification} class to define the properties of your +status bar notification, such as the status bar icon, the notification message, and extra settings +such as a sound to play. The {@link android.app.NotificationManager} is an Android system service +that executes and manages all status bar notifications. You do not instantiate the +{@link android.app.NotificationManager} directly. In order +to give it your {@link android.app.Notification}, you must retrieve a reference to the +{@link android.app.NotificationManager} with +{@link android.app.Activity#getSystemService(String) getSystemService()} and +then, when you want to notify the user, pass it your {@link android.app.Notification} with {@link android.app.NotificationManager#notify(int,Notification) notify()}. </p> <p>To create a status bar notification:</p> <ol> - <li>Get a reference to the NotificationManager: + <li>Get a reference to the {@link android.app.NotificationManager}: <pre> String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); </pre> </li> - <li>Instantiate the Notification: + <!-- use Notification.Builder in 3.0 --> + <li>Instantiate the {@link android.app.Notification}: <pre> int icon = R.drawable.notification_icon; CharSequence tickerText = "Hello"; @@ -95,7 +101,7 @@ long when = System.currentTimeMillis(); Notification notification = new Notification(icon, tickerText, when); </pre> </li> - <li>Define the Notification's expanded message and Intent: + <li>Define the notification's message and {@link android.app.PendingIntent}: <pre> Context context = getApplicationContext(); CharSequence contentTitle = "My notification"; @@ -106,7 +112,7 @@ PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationInt notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); </pre> </li> - <li>Pass the Notification to the NotificationManager: + <li>Pass the {@link android.app.Notification} to the {@link android.app.NotificationManager}: <pre> private static final int HELLO_ID = 1; @@ -121,38 +127,41 @@ mNotificationManager.notify(HELLO_ID, notification); <p>The {@link android.app.NotificationManager} is a system service that manages all notifications. You must retrieve a reference to it with the -{@link android.app.Activity#getSystemService(String) getSystemService()} method. +{@link android.app.Activity#getSystemService(String) getSystemService()} method. For example:</p> <pre> String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); </pre> -<p>When you want to send your status bar notification, pass the Notification object -to the NotificationManager with {@link android.app.NotificationManager#notify(int,Notification)}. -The first parameter is the unique ID for the Notification and the second is the Notification object. -The ID uniquely identifies the Notification from within your -application. This is necessary if you need to update the Notification or (if -your application manages different kinds of Notifications) select the appropriate action -when the user returns to your application via the Intent defined in the Notification.</p> +<p>When you want to deliver your status bar notification, pass the {@link android.app.Notification} +to the {@link android.app.NotificationManager} with {@link +android.app.NotificationManager#notify(int,Notification)}. +The first parameter is the unique ID for the notification and the second is the {@link +android.app.Notification} object. +The ID uniquely identifies the notification from within your +application. The ID is necessary if you need to update the notification or (if +your application manages different kinds of notifications) select the appropriate action +when the user returns to your application via the intent defined in the notification.</p> -<p>To clear the status bar notification when the user selects it from the Notifications -window, add the "FLAG_AUTO_CANCEL" flag to your Notification object. You can also clear it -manually with {@link android.app.NotificationManager#cancel(int)}, passing it the notification ID, -or clear all your Notifications with {@link android.app.NotificationManager#cancelAll()}.</p> +<p>To clear the status bar notification when the user selects it from the notifications +window, add the "FLAG_AUTO_CANCEL" flag to your {@link android.app.Notification}. You can +also clear it manually with {@link android.app.NotificationManager#cancel(int)}, passing it the +notification ID, or clear all your notifications with {@link +android.app.NotificationManager#cancelAll()}.</p> <h2 id="CreateANotification">Creating a Notification</h2> <p>A {@link android.app.Notification} object defines the details of the notification -message that is displayed in the status bar and "Notifications" window, and any other +message that is displayed in the status bar and notifications window, and any other alert settings, such as sounds and blinking lights.</p> <p>A status bar notification <em>requires</em> all of the following:</p> <ul> <li>An icon for the status bar</li> - <li>A title and expanded message for the expanded view (unless you define a - <a href="#CustomExpandedView">custom expanded view</a>)</li> + <li>A title and message, unless you define a + <a href="#CustomExpandedView">custom notification layout</a></li> <li>A {@link android.app.PendingIntent}, to be fired when the notification is selected</li> </ul> <p>Optional settings for the status bar notification include:</p> @@ -163,18 +172,18 @@ alert settings, such as sounds and blinking lights.</p> <li>A flashing LED setting</li> </ul> -<p>The starter-kit for a new Notification includes the -{@link android.app.Notification#Notification(int,CharSequence,long)} constructor and the -{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)} -method. These define all the required settings for a Notification. -The following snippet demonstrates a basic Notification setup:</p> +<p>The starter-kit for a new notification includes the +{@link android.app.Notification#Notification(int,CharSequence,long)} constructor and the +{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)} +method. These define all the required settings for a notification. +The following snippet demonstrates a basic notification setup:</p> <pre> int icon = R.drawable.notification_icon; // icon from resources CharSequence tickerText = "Hello"; // ticker-text long when = System.currentTimeMillis(); // notification time Context context = getApplicationContext(); // application Context -CharSequence contentTitle = "My notification"; // expanded message title -CharSequence contentText = "Hello World!"; // expanded message text +CharSequence contentTitle = "My notification"; // message title +CharSequence contentText = "Hello World!"; // message text Intent notificationIntent = new Intent(this, MyClass.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); @@ -187,32 +196,33 @@ notification.setLatestEventInfo(context, contentTitle, contentText, contentInten <h3 id="Updating">Updating the notification</h3> -<p>You can update the information in your status bar notification as events -continue to occur in your application. For example, when a new SMS text message arrives -before previous messages have been read, the Messaging application updates the existing +<p>You can update the information in your status bar notification as events +continue to occur in your application. For example, when a new SMS text message arrives +before previous messages have been read, the Messaging application updates the existing notification to display the total number of new messages received. -This practice of updating an existing Notification is much better than adding new Notifications -to the NotificationManager because it avoids clutter in the Notifications window.</p> +This practice of updating an existing notification is much better than adding new +notifications, because it avoids clutter in the notifications window.</p> <p>Because each notification is uniquely identified -by the NotificationManager with an integer ID, you can revise the notification by calling -{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent) -setLatestEventInfo()} with new values, change some field values of the Notification, and then call +by the {@link android.app.NotificationManager} with an integer ID, you can revise the notification +by calling {@link +android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent) +setLatestEventInfo()} with new values, change some field values of the notification, and then call {@link android.app.NotificationManager#notify(int,Notification) notify()} again.</p> <p>You can revise each property with the object member fields -(except for the Context and the expanded message title and text). You should always -revise the text message when you update the notification by calling +(except for the {@link android.content.Context} and the notification title and text). You +should always revise the text message when you update the notification by calling {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent) -setLatestEventInfo()} with new values for <var>contentTitle</var> and <var>contentText</var>. -Then call {@link android.app.NotificationManager#notify(int,Notification) notify()} to update the -notification. (Of course, if you've created a <a href="#CustomExpandedView">custom expanded -view</a>, then updating these title and text values has no effect.)</p> +setLatestEventInfo()} with new values for <var>contentTitle</var> and <var>contentText</var>. +Then call {@link android.app.NotificationManager#notify(int,Notification) notify()} to update the +notification. (Of course, if you've created a <a href="#CustomExpandedView">custom notification +layout</a>, then updating these title and text values has no effect.)</p> <h3 id="Sound">Adding a sound</h3> -<p>You can alert the user with the default notification sound +<p>You can alert the user with the default notification sound (which is defined by the user) or with a sound specified by your application.</p> <p>To use the user's default sound, add "DEFAULT_SOUND" to the <var>defaults</var> field:</p> @@ -227,31 +237,35 @@ The following example uses a known audio file saved to the device SD card:</p> notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3"); </pre> -<p>In the next example, the audio file is chosen from the internal +<p>In the next example, the audio file is chosen from the internal {@link android.provider.MediaStore.Audio.Media MediaStore}'s {@link android.content.ContentProvider}:</p> <pre> notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6"); </pre> -<p>In this case, the exact ID of the media file ("6") is known and appended to the content +<p>In this case, the exact ID of the media file ("6") is known and appended to the content {@link android.net.Uri}. If you don't know the exact ID, you must query all the -media available in the MediaStore with a {@link android.content.ContentResolver}. +media available in the {@link android.provider.MediaStore} with a {@link +android.content.ContentResolver}. See the <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> documentation for more information on using a ContentResolver.</p> <p>If you want the sound to continuously repeat until the user responds to the notification -or the notification is cancelled, add "FLAG_INSISTENT" to the <var>flags</var> field.</p> +or the notification is cancelled, add {@link android.app.Notification#FLAG_INSISTENT} to the +<var>flags</var> field.</p> -<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes -"DEFAULT_SOUND", then the default sound overrides any sound defined by the <var>sound</var> field.</p> +<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes +{@link android.app.Notification#DEFAULT_SOUND}, then the default sound overrides any sound defined +by the <var>sound</var> field.</p> <h3 id="Vibration">Adding vibration</h3> -<p>You can alert the user with the the default +<p>You can alert the user with the the default vibration pattern or with a vibration pattern defined by your application.</p> -<p>To use the default pattern, add "DEFAULT_VIBRATE" to the <var>defaults</var> field:</p> +<p>To use the default pattern, add {@link android.app.Notification#DEFAULT_VIBRATE} to the +<var>defaults</var> field:</p> <pre> notification.defaults |= Notification.DEFAULT_VIBRATE; </pre> @@ -264,30 +278,32 @@ notification.vibrate = vibrate; </pre> <p>The long array defines the alternating pattern for the length of vibration off and on -(in milliseconds). The first value is how long to wait (off) before beginning, the second -value is the length of the first vibration, the third is the next length off, and so on. +(in milliseconds). The first value is how long to wait (off) before beginning, the second +value is the length of the first vibration, the third is the next length off, and so on. The pattern can be as long as you like, but it can't be set to repeat. </p> -<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes -"DEFAULT_VIBRATE", then the default vibration overrides any vibration defined by the +<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes +{@link android.app.Notification#DEFAULT_VIBRATE}, then the default vibration overrides any vibration +defined by the <var>vibrate</var> field.</p> <h3 id="Lights">Adding flashing lights</h3> -<p>To alert the user by flashing LED lights, you can implement the default +<p>To alert the user by flashing LED lights, you can implement the default light pattern (if available), or define your own color and pattern for the lights.</p> -<p>To use the default light setting, add "DEFAULT_LIGHTS" to the <var>defaults</var> field:</p> +<p>To use the default light setting, add {@link android.app.Notification#DEFAULT_LIGHTS} to the +<var>defaults</var> field:</p> <pre> notification.defaults |= Notification.DEFAULT_LIGHTS; </pre> <p>To define your own color and pattern, define a value for the <var>ledARGB</var> field -(for the color), the <var>ledOffMS</var> field (length of time, in milliseconds, to -keep the light off), the <var>ledOnMS</var> (length of time, in milliseconds, to keep the light on), -and also add "FLAG_SHOW_LIGHTS" to the <var>flags</var> field:</p> +(for the color), the <var>ledOffMS</var> field (length of time, in milliseconds, to +keep the light off), the <var>ledOnMS</var> (length of time, in milliseconds, to keep the light on), +and also add {@link android.app.Notification#FLAG_SHOW_LIGHTS} to the <var>flags</var> field:</p> <pre> notification.ledARGB = 0xff00ff00; notification.ledOnMS = 300; @@ -295,114 +311,161 @@ notification.ledOffMS = 1000; notification.flags |= Notification.FLAG_SHOW_LIGHTS; </pre> -<p>In this example, the green light repeatedly flashes on for 300 milliseconds and -turns off for one second. Not every color in the spectrum is supported by the -device LEDs, and not every device supports the same colors, so the hardware +<p>In this example, the green light repeatedly flashes on for 300 milliseconds and +turns off for one second. Not every color in the spectrum is supported by the +device LEDs, and not every device supports the same colors, so the hardware estimates to the best of its ability. Green is the most common notification color.</p> <h3 id="More">More features</h3> <p>You can add several more features to your notifications -using Notification fields and flags. Some useful features include the following:</p> +using {@link android.app.Notification} fields and flags. Some useful features include the +following:</p> <dl> - <dt>"FLAG_AUTO_CANCEL" flag</dt> + <dt>{@link android.app.Notification#FLAG_AUTO_CANCEL} flag</dt> <dd>Add this to the <var>flags</var> field to automatically cancel the notification - after it is selected from the Notifications window.</dd> - <dt>"FLAG_INSISTENT" flag</dt> + after it is selected from the notifications window.</dd> + <dt>{@link android.app.Notification#FLAG_INSISTENT} flag</dt> <dd>Add this to the <var>flags</var> field to repeat the audio until the user responds.</dd> - <dt>"FLAG_ONGOING_EVENT" flag</dt> + <dt>{@link android.app.Notification#FLAG_ONGOING_EVENT} flag</dt> <dd>Add this to the <var>flags</var> field to group the notification under the "Ongoing" - title in the Notifications window. This indicates that the application is on-going — - its processes is still running in the background, even when the application is not + title in the notifications window. This indicates that the application is on-going — + its processes are still running in the background, even when the application is not visible (such as with music or a phone call).</dd> - <dt>"FLAG_NO_CLEAR" flag</dt> - <dd>Add this to the <var>flags</var> field to indicate that the notification should - <em>not</em> be cleared by the "Clear notifications" button. This is particularly useful if + <dt>{@link android.app.Notification#FLAG_NO_CLEAR} flag</dt> + <dd>Add this to the <var>flags</var> field to indicate that the notification should + <em>not</em> be cleared by the "Clear notifications" button. This is particularly useful if your notification is on-going.</dd> - <dt><var>number</var> field</dt> + <dt>{@link android.app.Notification#number} field</dt> <dd>This value indicates the current number of events represented by the notification. The appropriate number is overlaid on top of the status bar icon. If you intend to use this field, then you must start with "1" when the Notification is first created. (If you change the value from zero to anything greater during an update, the number is not shown.)</dd> - <dt><var>iconLevel</var> field</dt> - <dd>This value indicates the current level of a + <dt>{@link android.app.Notification#iconLevel} field</dt> + <dd>This value indicates the current level of a {@link android.graphics.drawable.LevelListDrawable} that is used for the notification icon. - You can animate the icon in the status bar by changing this value to correlate with the + You can animate the icon in the status bar by changing this value to correlate with the drawable's defined in a LevelListDrawable. See the {@link android.graphics.drawable.LevelListDrawable} reference for more information.</dd> </dl> -<p>See the {@link android.app.Notification} class reference for more information about additional +<p>See the {@link android.app.Notification} class reference for more information about additional features that you can customize for your application.</p> -<h2 id="CustomExpandedView">Creating a Custom Expanded View</h2> +<h2 id="CustomExpandedView">Creating a Custom Notification Layout</h2> -<img src="{@docRoot}images/custom_message.png" alt="" style="float:right;" /> +<div class="figure" style="width:200px;margin-top:0"> +<img src="{@docRoot}images/custom_message.png" alt="" /> +<p class="img-caption"><strong>Figure 3.</strong> Notification with a custom layout.</p> +</div> -<p>By default, the expanded view used in the "Notifications" window includes a basic title and text -message. These are defined by the <var>contentTitle</var> and <var>contentText</var> +<p>By default, the notification that appears in the notifications window includes a title +and the message text. +These are defined by the <var>contentTitle</var> and <var>contentText</var> parameters of the {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent) -setLatestEventInfo()} method. However, you can also define a custom layout for the expanded view using -{@link android.widget.RemoteViews}. The screenshot to the right shows an example of a -custom expanded view that uses an ImageView and TextView in a LinearLayout.</p> +setLatestEventInfo()} method. However, you can also define a custom layout for the +notification using +{@link android.widget.RemoteViews}. Figure 3 shows an example of a +custom notification layout. It looks similar to the default notification, but is +actually created with a custom XML layout.</p> -<p>To define your own layout for the expanded message, -instantiate a {@link android.widget.RemoteViews} object and -pass it to the <var>contentView</var> field of your Notification. Pass the -{@link android.app.PendingIntent} to the <var>contentIntent</var> field.</p> +<p>To define your own layout for the notification, +instantiate a {@link android.widget.RemoteViews} object that inflates a custom layout file, then +pass the {@link android.widget.RemoteViews} to the <var>contentView</var> field of your +Notification.</p> -<p>Creating a custom expanded view is best understood with an example:</p> +<p>Creating a custom notification layout is best understood with an example:</p> <ol> - <li>Create the XML layout for the expanded view. - For example, create a layout file called <code>custom_notification_layout.xml</code> and - build it like so: + <li>Create the XML layout for the notification. + For example, the following layout is called <code>custom_notification.xml</code>: <pre> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="horizontal" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:padding="3dp" - > +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/layout" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:padding="10dp" > <ImageView android:id="@+id/image" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_marginRight="10dp" - /> + android:layout_width="wrap_content" + android:layout_height="fill_parent" + android:layout_alignParentLeft="true" + android:layout_marginRight="10dp" /> + <TextView android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@id/image" + style="@style/NotificationTitle" /> <TextView android:id="@+id/text" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:textColor="#000" - /> -</LinearLayout> + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@id/image" + android:layout_below="@id/title" + style="@style/NotificationText" /> +</RelativeLayout> </pre> - <p>This layout is used for the expanded view, - but the content of the ImageView and TextView still needs to be defined by the application. - RemoteViews offers some convenient methods that allow you to define this content...</p> + <p>Notice that the two {@link android.widget.TextView} elements include the {@code style} +attribute. It's important that you use style resources for the text in your custom +notifications, because the background color of the notification can vary across different +devices and platform versions. Beginning with Android 2.3 (API level 9), the system defines a +style for the text it uses for the default notification layouts. Thus, you should apply +that style when running on Android 2.3 or higher to ensure that your text is visible against +the background.</p> + + <p>For example, to use the standard text colors on versions of Android lower than 2.3, you +should use the following styles for {@code res/values/styles.xml}:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="NotificationText"> + <item name="android:textColor">?android:attr/textColorPrimary</item> + </style> + <style name="NotificationTitle"> + <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textStyle">bold</item> + </style> + <!-- If you want a slightly different color for some text, + consider using ?android:attr/textColorSecondary --> +</resources> +</pre> + <p>Then, to apply the system's default colors for notifications on Android +2.3 and higher, use the following styles for {@code res/values-v9/styles.xml}:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" /> + <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" /> +</resources> +</pre> + <p>Now, when running on Android 2.3 (API level 9) or higher, the text in your custom view will +use the same colors that the system does for default notifications. This is important because later +versions of Android actually change the background color of the notifications to be dark. Inheriting +the system's styles ensures that your text will be light in such cases, but also if the background +is some other unexpected color, your text will also change as appropriate.</p> </li> - <li>In the application code, use the RemoveViews + <li>Now, in the application code, use the RemoveViews methods to define the image and text. Then pass the RemoteViews object to the <var>contentView</var> field of the Notification, as shown in this example: <pre> RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout); contentView.setImageViewResource(R.id.image, R.drawable.notification_image); -contentView.setTextViewText(R.id.text, "Hello, this message is in a custom expanded view"); +contentView.setTextViewText(R.id.title, "Custom notification"); +contentView.setTextViewText(R.id.text, "This is a custom layout"); notification.contentView = contentView; </pre> - <p>As shown here, pass the application's package name and the layout + <p>As shown here, pass the application's package name and the layout resource ID to the RemoteViews constructor. Then, define the content for the ImageView and TextView, using the {@link android.widget.RemoteViews#setImageViewResource(int, int) setImageViewResource()} and {@link android.widget.RemoteViews#setTextViewText(int, CharSequence) setTextViewText()}. In each case, pass the reference ID of the appropriate View object that you want to set, along with - the value for that View. Finally, the RemoteViews object is passed to the Notification in the + the value for that View. Finally, the RemoteViews object is passed to the Notification in the <var>contentView</var> field.</p> </li> @@ -416,23 +479,23 @@ PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationInt notification.contentIntent = contentIntent; </pre> </li> - + <li>The notification can now be sent as usual: <pre>mNotificationManager.notify(CUSTOM_VIEW_ID, notification);</pre> </li> </ol> -<p>The RemoteViews class also includes methods that you can use to easily add a -{@link android.widget.Chronometer} or {@link android.widget.ProgressBar} -in your notification's expanded view. For more information about creating custom layouts with -RemoteViews, refer to the {@link android.widget.RemoteViews} class reference.</p> +<p>The {@link android.widget.RemoteViews} class also includes methods that you can use to easily add +a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar} +in your notification's layout. For more information about creating custom layouts for your +notification, refer to the {@link android.widget.RemoteViews} class reference.</p> -<p class="warning"><strong>Note:</strong> -When creating a custom expanded view, you must take special care to ensure that your -custom layout functions properly in different device orientations and resolutions. While this +<p class="caution"><strong>Caution:</strong> +When creating a custom notification layout, you must take special care to ensure that your +custom layout functions properly in different device orientations and resolutions. While this advice applies to all View layouts created on Android, it is especially important in this case -because your layout real estate is very restricted. So don't make your custom layout too +because your layout real estate is very restricted. So don't make your custom layout too complex and be sure to test it in various configurations.</p> diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd index 463ec9c2015a..120576bf5bc0 100644 --- a/docs/html/guide/topics/usb/adk.jd +++ b/docs/html/guide/topics/usb/adk.jd @@ -77,6 +77,10 @@ page.title=Android Open Accessory Development Kit DIY Drones</a></li> <li><a href= + "http://mbed.org/order/"> + mbed</a></li> + + <li><a href= "http://www.microchip.com/android"> Microchip</a></li> @@ -130,6 +134,11 @@ page.title=Android Open Accessory Development Kit Drones</a> provides an Arduino-compatible board geared towards RC (radio controlled) and UAV (unmanned aerial vehicle) enthusiasts.</li> + <li><a href="http://mbed.org/order/">mbed</a> provides a microcontroller and a library + to develop accessories that support the Android accessory protocol. For more information, see + <a href="http://mbed.org/cookbook/mbed-with-Android-ADK">mbed with the Android ADK</a>. + </li> + <li><a href="http://www.microchip.com/android">Microchip</a> provides a PIC based USB microcontroller board.</li> diff --git a/docs/html/images/custom_message.png b/docs/html/images/custom_message.png Binary files differindex ea7c7160e020..00b763239c40 100755 --- a/docs/html/images/custom_message.png +++ b/docs/html/images/custom_message.png diff --git a/docs/html/images/widget_design/2x2_Widget_Frame_Landscape.png b/docs/html/images/widget_design/2x2_Widget_Frame_Landscape.png Binary files differdeleted file mode 100644 index a73a09a61f8d..000000000000 --- a/docs/html/images/widget_design/2x2_Widget_Frame_Landscape.png +++ /dev/null diff --git a/docs/html/images/widget_design/2x2_Widget_Frame_Landscape.psd b/docs/html/images/widget_design/2x2_Widget_Frame_Landscape.psd Binary files differdeleted file mode 100644 index cd869b5861f3..000000000000 --- a/docs/html/images/widget_design/2x2_Widget_Frame_Landscape.psd +++ /dev/null diff --git a/docs/html/images/widget_design/2x2_Widget_Frame_Portrait.png b/docs/html/images/widget_design/2x2_Widget_Frame_Portrait.png Binary files differdeleted file mode 100644 index 95ac03118c42..000000000000 --- a/docs/html/images/widget_design/2x2_Widget_Frame_Portrait.png +++ /dev/null diff --git a/docs/html/images/widget_design/2x2_Widget_Frame_Portrait.psd b/docs/html/images/widget_design/2x2_Widget_Frame_Portrait.psd Binary files differdeleted file mode 100644 index 9f0a7b0cf3af..000000000000 --- a/docs/html/images/widget_design/2x2_Widget_Frame_Portrait.psd +++ /dev/null diff --git a/docs/html/images/widget_design/3x3_Widget_Frame_Landscape.png b/docs/html/images/widget_design/3x3_Widget_Frame_Landscape.png Binary files differdeleted file mode 100644 index 14013dc0973d..000000000000 --- a/docs/html/images/widget_design/3x3_Widget_Frame_Landscape.png +++ /dev/null diff --git a/docs/html/images/widget_design/3x3_Widget_Frame_Landscape.psd b/docs/html/images/widget_design/3x3_Widget_Frame_Landscape.psd Binary files differdeleted file mode 100644 index 50a2b8ca0808..000000000000 --- a/docs/html/images/widget_design/3x3_Widget_Frame_Landscape.psd +++ /dev/null diff --git a/docs/html/images/widget_design/3x3_Widget_Frame_Portrait.png b/docs/html/images/widget_design/3x3_Widget_Frame_Portrait.png Binary files differdeleted file mode 100644 index 22f99f8631b0..000000000000 --- a/docs/html/images/widget_design/3x3_Widget_Frame_Portrait.png +++ /dev/null diff --git a/docs/html/images/widget_design/3x3_Widget_Frame_Portrait.psd b/docs/html/images/widget_design/3x3_Widget_Frame_Portrait.psd Binary files differdeleted file mode 100644 index 591e963d6e02..000000000000 --- a/docs/html/images/widget_design/3x3_Widget_Frame_Portrait.psd +++ /dev/null diff --git a/docs/html/images/widget_design/4x1_Widget_Frame_Landscape.png b/docs/html/images/widget_design/4x1_Widget_Frame_Landscape.png Binary files differdeleted file mode 100644 index c6a3f7adea71..000000000000 --- a/docs/html/images/widget_design/4x1_Widget_Frame_Landscape.png +++ /dev/null diff --git a/docs/html/images/widget_design/4x1_Widget_Frame_Landscape.psd b/docs/html/images/widget_design/4x1_Widget_Frame_Landscape.psd Binary files differdeleted file mode 100644 index ec811798ba05..000000000000 --- a/docs/html/images/widget_design/4x1_Widget_Frame_Landscape.psd +++ /dev/null diff --git a/docs/html/images/widget_design/4x1_Widget_Frame_Portrait.png b/docs/html/images/widget_design/4x1_Widget_Frame_Portrait.png Binary files differdeleted file mode 100644 index 5cc8665cdb67..000000000000 --- a/docs/html/images/widget_design/4x1_Widget_Frame_Portrait.png +++ /dev/null diff --git a/docs/html/images/widget_design/4x1_Widget_Frame_Portrait.psd b/docs/html/images/widget_design/4x1_Widget_Frame_Portrait.psd Binary files differdeleted file mode 100644 index bad7ad126811..000000000000 --- a/docs/html/images/widget_design/4x1_Widget_Frame_Portrait.psd +++ /dev/null diff --git a/docs/html/images/widget_design/Add_Noise.png b/docs/html/images/widget_design/Add_Noise.png Binary files differdeleted file mode 100644 index c323bb490c36..000000000000 --- a/docs/html/images/widget_design/Add_Noise.png +++ /dev/null diff --git a/docs/html/images/widget_design/Layer_Style.png b/docs/html/images/widget_design/Layer_Style.png Binary files differdeleted file mode 100644 index 757780314244..000000000000 --- a/docs/html/images/widget_design/Layer_Style.png +++ /dev/null diff --git a/docs/html/images/widget_design/Music_widget_button_states.psd b/docs/html/images/widget_design/Music_widget_button_states.psd Binary files differdeleted file mode 100644 index 17f3573d5097..000000000000 --- a/docs/html/images/widget_design/Music_widget_button_states.psd +++ /dev/null diff --git a/docs/html/images/widget_design/alignment.png b/docs/html/images/widget_design/alignment.png Binary files differdeleted file mode 100644 index 2e794dde0ea0..000000000000 --- a/docs/html/images/widget_design/alignment.png +++ /dev/null diff --git a/docs/html/images/widget_design/buttons.png b/docs/html/images/widget_design/buttons.png Binary files differdeleted file mode 100644 index a6d1df275f99..000000000000 --- a/docs/html/images/widget_design/buttons.png +++ /dev/null diff --git a/docs/html/images/widget_design/file_format.png b/docs/html/images/widget_design/file_format.png Binary files differdeleted file mode 100644 index 26f0e562ab67..000000000000 --- a/docs/html/images/widget_design/file_format.png +++ /dev/null diff --git a/docs/html/images/widget_design/landscape_sizes.png b/docs/html/images/widget_design/landscape_sizes.png Binary files differdeleted file mode 100644 index 798bb159fd66..000000000000 --- a/docs/html/images/widget_design/landscape_sizes.png +++ /dev/null diff --git a/docs/html/images/widget_design/music_example.png b/docs/html/images/widget_design/music_example.png Binary files differnew file mode 100644 index 000000000000..885057e0a568 --- /dev/null +++ b/docs/html/images/widget_design/music_example.png diff --git a/docs/html/images/widget_design/music_example_layouts.png b/docs/html/images/widget_design/music_example_layouts.png Binary files differnew file mode 100644 index 000000000000..31601b94452c --- /dev/null +++ b/docs/html/images/widget_design/music_example_layouts.png diff --git a/docs/html/images/widget_design/music_example_redline.png b/docs/html/images/widget_design/music_example_redline.png Binary files differnew file mode 100644 index 000000000000..85794b8936b3 --- /dev/null +++ b/docs/html/images/widget_design/music_example_redline.png diff --git a/docs/html/images/widget_design/music_example_stretched.png b/docs/html/images/widget_design/music_example_stretched.png Binary files differnew file mode 100644 index 000000000000..28c2fb3cbfaf --- /dev/null +++ b/docs/html/images/widget_design/music_example_stretched.png diff --git a/docs/html/images/widget_design/portrait_sizes.png b/docs/html/images/widget_design/portrait_sizes.png Binary files differdeleted file mode 100644 index 9da252a4782c..000000000000 --- a/docs/html/images/widget_design/portrait_sizes.png +++ /dev/null diff --git a/docs/html/images/widget_design/widget_examples.png b/docs/html/images/widget_design/widget_examples.png Binary files differindex e27ffbb24cfe..277b69a8bd53 100644 --- a/docs/html/images/widget_design/widget_examples.png +++ b/docs/html/images/widget_design/widget_examples.png diff --git a/docs/html/images/widget_design/widget_sizes_landscape.png b/docs/html/images/widget_design/widget_sizes_landscape.png Binary files differdeleted file mode 100644 index 052e28e24925..000000000000 --- a/docs/html/images/widget_design/widget_sizes_landscape.png +++ /dev/null diff --git a/docs/html/images/widget_design/widget_sizes_portrait.png b/docs/html/images/widget_design/widget_sizes_portrait.png Binary files differdeleted file mode 100644 index 31a240c052c4..000000000000 --- a/docs/html/images/widget_design/widget_sizes_portrait.png +++ /dev/null diff --git a/docs/html/images/widget_design/widget_template_excerpts.png b/docs/html/images/widget_design/widget_template_excerpts.png Binary files differnew file mode 100644 index 000000000000..aba09e248cd7 --- /dev/null +++ b/docs/html/images/widget_design/widget_template_excerpts.png diff --git a/docs/html/images/widget_design/widget_terms.png b/docs/html/images/widget_design/widget_terms.png Binary files differnew file mode 100644 index 000000000000..5c4d09d6a24a --- /dev/null +++ b/docs/html/images/widget_design/widget_terms.png diff --git a/docs/html/resources/articles/speech-input.jd b/docs/html/resources/articles/speech-input.jd index 736087ecb2f4..0867ff26b023 100644 --- a/docs/html/resources/articles/speech-input.jd +++ b/docs/html/resources/articles/speech-input.jd @@ -87,8 +87,8 @@ while the "web search" model is used when users want to search by voice. </p> regularly. You can use the {@link android.speech.RecognizerIntent#ACTION_GET_LANGUAGE_DETAILS} broadcast intent to query for the list of supported languages. -The web search model is available in all three languages, while free-form has -primarily been optimized for English. As we work hard to support more models in +The web search model is available for all languages, while the free-form model +may not be optimized for all languages. As we work hard to support more models in more languages, and to improve the accuracy of the speech recognition technology we use in our products, Android developers who integrate speech capabilities directly into their applications can reap the benefits as well. </p> diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js index 720e14314c2a..6c5d882908d0 100644 --- a/docs/html/resources/resources-data.js +++ b/docs/html/resources/resources-data.js @@ -31,7 +31,8 @@ var ANDROID_TAGS = { }, misc: { 'external': 'External', - 'new': 'New' + 'new': 'New', + 'updated': 'Updated' } }; @@ -322,6 +323,16 @@ var ANDROID_RESOURCES = [ } }, { + tags: ['article', 'accountsync', 'data'], + path: 'articles/contacts.html', + title: { + en: 'Using the Contacts API' + }, + description: { + en: 'Android provides a Contacts API for managing and integrating contacts from multiple accounts and data sources and allows apps to read various information about individual contacts.' + } + }, + { tags: ['article', 'ui', 'web'], path: 'articles/using-webviews.html', title: { @@ -377,7 +388,7 @@ var ANDROID_RESOURCES = [ /////////////////// { - tags: ['sample', 'new'], + tags: ['sample'], path: 'samples/AccelerometerPlay/index.html', title: { en: 'Accelerometer Play' @@ -387,7 +398,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'new', 'accessibility'], + tags: ['sample', 'accessibility'], path: 'samples/AccessibilityService/index.html', title: { en: 'Accessibility Service' @@ -407,7 +418,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'layout', 'ui', 'fragment', 'loader', 'new'], + tags: ['sample', 'layout', 'ui', 'fragment', 'loader'], path: 'samples/Support4Demos/index.html', title: { en: 'API 4+ Support Demos' @@ -417,7 +428,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'layout', 'ui', 'new'], + tags: ['sample', 'layout', 'ui'], path: 'samples/Support13Demos/index.html', title: { en: 'API 13+ Support Demos' @@ -487,13 +498,13 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'new', 'newfeature', 'ui'], + tags: ['sample', 'updated', 'newfeature', 'ui'], path: 'samples/HoneycombGallery/index.html', title: { en: 'Honeycomb Gallery' }, description: { - en: 'An image gallery application using APIs that are new in Android 3.0 (a.k.a. Honeycomb).' + en: 'An image gallery application that demonstrates a variety of new APIs in Android 3.0 (Honeycomb). In addition to providing a tablet-optimized design, it also supports handsets running Android 4.0 (Ice Cream Sandwich) and beyond, so is a good example of how to reuse Fragments to support different screen sizes.' } }, { @@ -547,7 +558,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'new', 'media' ], + tags: ['sample', 'media' ], path: 'samples/RandomMusicPlayer/index.html', title: { en: 'Random Music Player' @@ -557,7 +568,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'new', 'newfeature', 'performance', 'gamedev', 'gl'], + tags: ['sample', 'newfeature', 'performance', 'gamedev', 'gl'], path: 'samples/RenderScript/index.html', title: { en: 'RenderScript' @@ -637,7 +648,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'new', 'newfeature', 'widgets'], + tags: ['sample', 'newfeature', 'widgets'], path: 'samples/StackWidget/index.html', title: { en: 'StackView Widget' @@ -667,7 +678,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'new', 'newfeature'], + tags: ['sample', 'newfeature'], path: 'samples/USB/index.html', title: { en: 'USB' @@ -683,7 +694,7 @@ var ANDROID_RESOURCES = [ en: 'Voicemail Provider Demo' }, description: { - en: 'A sample application to demonstrate how to use voicemail content provider APIs.' + en: 'A sample application to demonstrate how to use voicemail content provider APIs in Android 4.0.' } }, { @@ -707,7 +718,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'widgets', 'newfeature', 'new'], + tags: ['sample', 'widgets', 'newfeature'], path: 'samples/WeatherListWidget/index.html', title: { en: 'Weather List Widget' @@ -733,7 +744,7 @@ var ANDROID_RESOURCES = [ en: 'Text To Speech Engine' }, description: { - en: 'An example Text To Speech engine written using the android text to speech engine API.' + en: 'An example Text To Speech engine written using the Android text to speech engine API in Android 4.0.' } }, diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd index 5cf37c120233..105c868f835c 100644 --- a/docs/html/sdk/index.jd +++ b/docs/html/sdk/index.jd @@ -1,21 +1,21 @@ page.title=Android SDK sdk.redirect=0 -sdk.win_installer=installer_r12-windows.exe -sdk.win_installer_bytes=36531492 -sdk.win_installer_checksum=367f0ed4ecd70aefc290d1f7dcb578ab +sdk.win_installer=installer_r13-windows.exe +sdk.win_installer_bytes=36533357 +sdk.win_installer_checksum=cd3a76fe2b8ed62b2d03cf1851692e2d -sdk.win_download=android-sdk_r12-windows.zip -sdk.win_bytes=36486190 -sdk.win_checksum=8d6c104a34cd2577c5506c55d981aebf +sdk.win_download=android-sdk_r13-windows.zip +sdk.win_bytes=36487911 +sdk.win_checksum=de8a039891e5e65b7742f188f07b992d -sdk.mac_download=android-sdk_r12-mac_x86.zip -sdk.mac_bytes=30231118 -sdk.mac_checksum=341544e4572b4b1afab123ab817086e7 +sdk.mac_download=android-sdk_r13-mac_x86.zip +sdk.mac_bytes=30233944 +sdk.mac_checksum=f4002a0344b48856c09dec796acecd4d -sdk.linux_download=android-sdk_r12-linux_x86.tgz -sdk.linux_bytes=30034243 -sdk.linux_checksum=f8485275a8dee3d1929936ed538ee99a +sdk.linux_download=android-sdk_r13-linux_x86.tgz +sdk.linux_bytes=30034328 +sdk.linux_checksum=d80d7530a46c665644ae76084a9a0dc4 @jd:body diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index a00ca125a6cf..8a57312a4690 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -77,7 +77,7 @@ class="new">new!</span></li> <ul> <li class="toggle-list"> <div><a href="<?cs var:toroot ?>sdk/android-3.2.html"> - <span class="en">Android 3.2 Platform</span></a> <span class="new">new!</span></div> + <span class="en">Android 3.2 Platform</span></a></div> <ul> <!-- <li><a href="<?cs var:toroot ?>sdk/android-3.2-highlights.html">Platform Highlights</a></li> --> <li><a href="<?cs var:toroot ?>sdk/api_diff/13/changes.html">API Differences Report »</a></li> @@ -142,11 +142,11 @@ class="new">new!</span></li> </li> </ul> <ul> - <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r12</a> <span + <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r13</a> <span class="new">new!</span></li> <li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li> <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Package, -r3</a> <span class="new">new!</span></li> +r3</a></li> </ul> </li> <li> @@ -169,7 +169,7 @@ r3</a> <span class="new">new!</span></li> <span style="display:none" class="ja"></span> <span style="display:none" class="zh-CN"></span> <span style="display:none" class="zh-TW"></span></a> - <span class="new">new!</span></li> + </li> </ul> </li> <li> @@ -183,8 +183,7 @@ r3</a> <span class="new">new!</span></li> <span style="display:none" class="zh-TW"></span> </h2> <ul> - <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6b</a> - <span class="new">new!</span> + <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6b</a> </li> <li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li> </ul> diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd index 8c4d0378e79c..2179cec6036d 100644 --- a/docs/html/sdk/tools-notes.jd +++ b/docs/html/sdk/tools-notes.jd @@ -4,7 +4,7 @@ page.title=SDK Tools <p>SDK Tools is a downloadable component for the Android SDK. It includes the complete set of development and debugging tools for the Android SDK. </p> -<p>If you are new to the Android SDK, the <a +<p>If you are new to the Android SDK, the <a href="{@docRoot}sdk/index.html">SDK starter package</a> installs the latest revision of the SDK Tools in the <code><sdk>/tools</code> directory.</p> @@ -66,6 +66,35 @@ padding: .25em 1em; <div class="toggleable opened"> <a href="#" onclick="return toggleDiv(this)"> <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" /> +SDK Tools, Revision 13</a> <em>(September 2011)</em> + <div class="toggleme"> + <dl> +<dt>Dependencies:</dt> +<dd> +<p>If you are developing in Eclipse with ADT, note that the SDK Tools r13 is designed for use with +ADT 12.0.0 and later. If you haven't already, we highly recommend updating your <a +href="{@docRoot}sdk/eclipse-adt.html">ADT Plugin</a> to 12.0.0.</p> + +<p>If you are developing outside Eclipse, you must have <a href="http://ant.apache.org/">Apache +Ant</a> 1.8 or later.</p> + +<dt>General notes:</dt> +<dd> + <ul> + <li>Fix compilation issue in Ant (<code>dex</code> step) when paths have spaces.</li> + <li>Fix issue in emulator installation when paths have spaces.</li> + <li>Fix issue when AVD paths have spaces.</li> + <li>Fix rendering issue when using emulator scaling (<a href="http://code.google.com/p/android/issues/detail?id=18299">see more</a>).</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" /> SDK Tools, Revision 12</a> <em>(July 2011)</em> <div class="toggleme"> <dl> @@ -396,7 +425,7 @@ install SDK Tools r4 in your SDK. </p></dd> <dt>General notes:</dt> <dd> <ul> -<li>Launcher script now forces GDK_NATIVE_WINDOW=true (linux only), to fix a +<li>Launcher script now forces GDK_NATIVE_WINDOW=true (linux only), to fix a compatibility issue between GTK and SWT.</li> </ul> </dd> @@ -405,7 +434,7 @@ compatibility issue between GTK and SWT.</li> <dd> <ul> <li>AVD Launch dialog now shows scale value.</li> -<li>Fixes potential NPE in SDK Manager on AVD launch, for older AVD with no +<li>Fixes potential NPE in SDK Manager on AVD launch, for older AVD with no skin name specified.</li> <li>Fixes XML validation issue in on older Java versions.</li> <li>No longer forces the use of Java 1.5 on Mac OS X.</li> @@ -470,7 +499,7 @@ display the trace.</li> <dd> <ul> <li>Provides a new UI that lets you set options for controlling -the emulator skin, screen size/density, and scale factor used when launching +the emulator skin, screen size/density, and scale factor used when launching an AVD.</li> <li>Provides improved AVD creation UI, which lets you customize the hardware properties of your AVDs.</li> @@ -481,11 +510,11 @@ between SDK add-ons and platforms.</li> <dt>Layoutopt, a new tool for optimizing layouts:</dt> -<dd><p>The SDK Tools r3 package includes <code>layoutopt</code>, a new command-line -tool that helps you optimize your layout hierarchies. When run against your -layout files, the tool analyzes their hierarchies and notifies you of -inefficiencies and other potential issues. The tool also provides simple -solutions for the issues it finds. For usage, see <a +<dd><p>The SDK Tools r3 package includes <code>layoutopt</code>, a new command-line +tool that helps you optimize your layout hierarchies. When run against your +layout files, the tool analyzes their hierarchies and notifies you of +inefficiencies and other potential issues. The tool also provides simple +solutions for the issues it finds. For usage, see <a href="/guide/developing/tools/layoutopt.html">layoutopt</a>.</p> </dd> </dl> diff --git a/docs/html/shareables/app_widget_templates-v4.0.zip b/docs/html/shareables/app_widget_templates-v4.0.zip Binary files differnew file mode 100644 index 000000000000..b16ef127c204 --- /dev/null +++ b/docs/html/shareables/app_widget_templates-v4.0.zip diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp index 3e4fe8c07d23..b2fa05378258 100644 --- a/drm/drmserver/DrmManager.cpp +++ b/drm/drmserver/DrmManager.cpp @@ -98,21 +98,27 @@ void DrmManager::removeUniqueId(int uniqueId) { } status_t DrmManager::loadPlugIns() { + + String8 vendorPluginDirPath("/vendor/lib/drm"); + loadPlugIns(vendorPluginDirPath); + String8 pluginDirPath("/system/lib/drm"); - return loadPlugIns(pluginDirPath); + loadPlugIns(pluginDirPath); + return DRM_NO_ERROR; + } status_t DrmManager::loadPlugIns(const String8& plugInDirPath) { - if (mSupportInfoToPlugInIdMap.isEmpty()) { - mPlugInManager.loadPlugIns(plugInDirPath); - Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); - for (unsigned int i = 0; i < plugInPathList.size(); ++i) { - String8 plugInPath = plugInPathList[i]; - DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0); - if (NULL != info) { + mPlugInManager.loadPlugIns(plugInDirPath); + Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); + for (unsigned int i = 0; i < plugInPathList.size(); ++i) { + String8 plugInPath = plugInPathList[i]; + DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0); + if (NULL != info) { + if (mSupportInfoToPlugInIdMap.indexOfKey(*info) < 0) { mSupportInfoToPlugInIdMap.add(*info, plugInPath); - delete info; } + delete info; } } return DRM_NO_ERROR; diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/graphics/java/android/renderscript/ProgramRaster.java index bc0d928a4b0e..60d9698df411 100644 --- a/graphics/java/android/renderscript/ProgramRaster.java +++ b/graphics/java/android/renderscript/ProgramRaster.java @@ -84,14 +84,10 @@ public class ProgramRaster extends BaseObj { public static class Builder { RenderScript mRS; boolean mPointSprite; - boolean mPointSmooth; - boolean mLineSmooth; CullMode mCullMode; public Builder(RenderScript rs) { mRS = rs; - mPointSmooth = false; - mLineSmooth = false; mPointSprite = false; mCullMode = CullMode.BACK; } @@ -108,8 +104,7 @@ public class ProgramRaster extends BaseObj { public ProgramRaster create() { mRS.validate(); - int id = mRS.nProgramRasterCreate(mPointSmooth, mLineSmooth, mPointSprite, - 1.f, mCullMode.mID); + int id = mRS.nProgramRasterCreate(mPointSprite, mCullMode.mID); return new ProgramRaster(id, mRS); } } diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java index 571b8952ebd6..e2950d5ed9f2 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -522,13 +522,10 @@ public class RenderScript { dstMode, depthFunc); } - native int rsnProgramRasterCreate(int con, boolean pointSmooth, boolean lineSmooth, - boolean pointSprite, float lineWidth, int cullMode); - synchronized int nProgramRasterCreate(boolean pointSmooth, boolean lineSmooth, - boolean pointSprite, float lineWidth, int cullMode) { + native int rsnProgramRasterCreate(int con, boolean pointSprite, int cullMode); + synchronized int nProgramRasterCreate(boolean pointSprite, int cullMode) { validate(); - return rsnProgramRasterCreate(mContext, pointSmooth, lineSmooth, pointSprite, lineWidth, - cullMode); + return rsnProgramRasterCreate(mContext, pointSprite, cullMode); } native void rsnProgramBindConstants(int con, int pv, int slot, int mID); diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp index d7ac5d8269d3..ec1f8dea7c7d 100644 --- a/graphics/jni/android_renderscript_RenderScript.cpp +++ b/graphics/jni/android_renderscript_RenderScript.cpp @@ -1053,12 +1053,10 @@ nProgramVertexCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader, // --------------------------------------------------------------------------- static jint -nProgramRasterCreate(JNIEnv *_env, jobject _this, RsContext con, jboolean pointSmooth, - jboolean lineSmooth, jboolean pointSprite, jfloat lineWidth, jint cull) +nProgramRasterCreate(JNIEnv *_env, jobject _this, RsContext con, jboolean pointSprite, jint cull) { - LOG_API("nProgramRasterCreate, con(%p), pointSmooth(%i), lineSmooth(%i), pointSprite(%i)", - con, pointSmooth, lineSmooth, pointSprite); - return (jint)rsProgramRasterCreate(con, pointSmooth, lineSmooth, pointSprite, lineWidth, (RsCullMode)cull); + LOG_API("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", con, pointSprite, cull); + return (jint)rsProgramRasterCreate(con, pointSprite, (RsCullMode)cull); } @@ -1295,7 +1293,7 @@ static JNINativeMethod methods[] = { {"rsnProgramBindSampler", "(IIII)V", (void*)nProgramBindSampler }, {"rsnProgramFragmentCreate", "(ILjava/lang/String;[I)I", (void*)nProgramFragmentCreate }, -{"rsnProgramRasterCreate", "(IZZZFI)I", (void*)nProgramRasterCreate }, +{"rsnProgramRasterCreate", "(IZI)I", (void*)nProgramRasterCreate }, {"rsnProgramVertexCreate", "(ILjava/lang/String;[I)I", (void*)nProgramVertexCreate }, {"rsnContextBindRootScript", "(II)V", (void*)nContextBindRootScript }, diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index 4a4bcfb819bc..a520a6a12e53 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -317,18 +317,13 @@ public: // recalculate exposure values). Changing exposure compensation // settings will still affect the exposure settings while // auto-exposure is locked. Stopping preview or taking a still - // image will release the lock. However, the lock can be - // re-enabled prior to preview being re-started, to keep the - // exposure values from the previous lock. In conjunction with + // image will not change the lock. In conjunction with // exposure compensation, this allows for capturing multi-exposure // brackets with known relative exposure values. Locking // auto-exposure after open but before the first call to // startPreview may result in severely over- or under-exposed - // images. The driver may independently enable the AE lock after - // auto-focus completes. If it does so, this key must have its - // value updated to reflect the lock's existence. Applications are - // free to release such a lock, to re-enable AE without restarting - // preview. + // images. The driver will not change the AE lock after + // auto-focus completes. static const char KEY_AUTO_EXPOSURE_LOCK[]; // Whether locking the auto-exposure is supported. "true" means it is, and // "false" or this key not existing means it is not supported. @@ -339,18 +334,13 @@ public: // change white balance values. If auto-white balance is already // locked, setting this to true again has no effect (the driver // will not recalculate white balance values). Stopping preview or - // taking a still image will release the lock. However, the lock - // can be re-enabled prior to preview being re-started, to keep - // the white balance values from the previous lock. In conjunction + // taking a still image will not change the lock. In conjunction // with exposure compensation, this allows for capturing // multi-exposure brackets with fixed white balance. Locking // auto-white balance after open but before the first call to // startPreview may result in severely incorrect color. The - // driver may independently enable the AWB lock after auto-focus - // completes. If it does so, this key must have its value updated - // to reflect the lock's existence. Applications are free to - // release such a lock, to re-enable AWB without restarting - // preview. + // driver will not change the AWB lock after auto-focus + // completes. static const char KEY_AUTO_WHITEBALANCE_LOCK[]; // Whether locking the auto-white balance is supported. "true" // means it is, and "false" or this key not existing means it is diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 493993d6d983..e2d6179ef046 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -20,13 +20,15 @@ #include <EGL/egl.h> #include <EGL/eglext.h> #include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> #include <gui/ISurfaceTexture.h> #include <ui/GraphicBuffer.h> -#include <utils/threads.h> +#include <utils/String8.h> #include <utils/Vector.h> +#include <utils/threads.h> #define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture" @@ -60,7 +62,8 @@ public: // tex indicates the name OpenGL texture to which images are to be streamed. // This texture name cannot be changed once the SurfaceTexture is created. - SurfaceTexture(GLuint tex, bool allowSynchronousMode = true); + SurfaceTexture(GLuint tex, bool allowSynchronousMode = true, + GLenum texTarget = GL_TEXTURE_EXTERNAL_OES); virtual ~SurfaceTexture(); @@ -202,6 +205,10 @@ public: // by OpenGL ES as a texture) then those buffer will remain allocated. void abandon(); + // set the name of the SurfaceTexture that will be used to identify it in + // log messages. + void setName(const String8& name); + // dump our state in a String void dump(String8& result) const; void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const; @@ -444,11 +451,23 @@ private: // all ISurfaceTexture methods capable of returning an error. bool mAbandoned; + // mName is a string used to identify the SurfaceTexture in log messages. + // It is set by the setName method. + String8 mName; + // mMutex is the mutex used to prevent concurrent access to the member // variables of SurfaceTexture objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; + // mTexTarget is the GL texture target with which the GL texture object is + // associated. It is set in the constructor and never changed. It is + // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android + // Browser. In that case it is set to GL_TEXTURE_2D to allow + // glCopyTexSubImage to read from the texture. This is a hack to work + // around a GL driver limitation on the number of FBO attachments, which the + // browser's tile cache exceeds. + const GLenum mTexTarget; }; // ---------------------------------------------------------------------------- diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index b7286e537319..5822877217c0 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -113,6 +113,7 @@ private: Vector<BufferInfo> mBuffers[2]; bool mPortEOS[2]; + status_t mInputEOSResult; List<sp<AMessage> > mDeferredQueue; @@ -150,6 +151,12 @@ private: OMX_VIDEO_CODINGTYPE compressionFormat); status_t setupAACDecoder(int32_t numChannels, int32_t sampleRate); + status_t setupAMRDecoder(bool isWAMR); + status_t setupG711Decoder(int32_t numChannels); + + status_t setupRawAudioFormat( + OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels); + status_t setMinBufferSize(OMX_U32 portIndex, size_t size); status_t initNativeWindow(); diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index 8baf5ec4b360..21b8c7443916 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -228,7 +228,7 @@ private: void setComponentRole(); void setAMRFormat(bool isWAMR, int32_t bitRate); - void setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate); + status_t setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate); void setG711Format(int32_t numChannels); status_t setVideoPortFormatType( diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 6b31ca4cb8bb..e0f4cf900adf 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -88,11 +88,6 @@ public: eElectronBeamAnimationOff = 0x10 }; - // flags for setOrientation - enum { - eOrientationAnimationDisable = 0x00000001 - }; - /* create connection with surface flinger, requires * ACCESS_SURFACE_FLINGER permission */ @@ -112,7 +107,8 @@ public: virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0; virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags) = 0; - /* Set display orientation. requires ACCESS_SURFACE_FLINGER permission */ + /* Set display orientation. requires ACCESS_SURFACE_FLINGER permission + * No flags are currently defined. Set flags to 0. */ virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags) = 0; /* signal that we're done booting. diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index f2bc81e9a70d..c72a45b89576 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -39,6 +39,12 @@ #define ALLOW_DEQUEUE_CURRENT_BUFFER false +// Macros for including the SurfaceTexture name in log messages +#define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__) +#define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__) +#define ST_LOGI(x, ...) LOGI("[%s] "x, mName.string(), ##__VA_ARGS__) +#define ST_LOGW(x, ...) LOGW("[%s] "x, mName.string(), ##__VA_ARGS__) +#define ST_LOGE(x, ...) LOGE("[%s] "x, mName.string(), ##__VA_ARGS__) namespace android { @@ -82,7 +88,14 @@ static float mtxRot270[16] = { static void mtxMul(float out[16], const float a[16], const float b[16]); -SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : +// Get an ID that's unique within this process. +static int32_t createProcessUniqueId() { + static volatile int32_t globalCounter = 0; + return android_atomic_inc(&globalCounter); +} + +SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode, + GLenum texTarget) : mDefaultWidth(1), mDefaultHeight(1), mPixelFormat(PIXEL_FORMAT_RGBA_8888), @@ -98,16 +111,21 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : mSynchronousMode(false), mAllowSynchronousMode(allowSynchronousMode), mConnectedApi(NO_CONNECTED_API), - mAbandoned(false) { - LOGV("SurfaceTexture::SurfaceTexture"); + mAbandoned(false), + mTexTarget(texTarget) { + // Choose a name using the PID and a process-unique ID. + mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); + + ST_LOGV("SurfaceTexture::SurfaceTexture"); sp<ISurfaceComposer> composer(ComposerService::getComposerService()); mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); mNextCrop.makeInvalid(); - memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix)); + memcpy(mCurrentTransformMatrix, mtxIdentity, + sizeof(mCurrentTransformMatrix)); } SurfaceTexture::~SurfaceTexture() { - LOGV("SurfaceTexture::~SurfaceTexture"); + ST_LOGV("SurfaceTexture::~SurfaceTexture"); freeAllBuffersLocked(); } @@ -151,22 +169,22 @@ status_t SurfaceTexture::setBufferCountServer(int bufferCount) { } status_t SurfaceTexture::setBufferCount(int bufferCount) { - LOGV("SurfaceTexture::setBufferCount"); + ST_LOGV("SurfaceTexture::setBufferCount"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("setBufferCount: SurfaceTexture has been abandoned!"); + ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!"); return NO_INIT; } if (bufferCount > NUM_BUFFER_SLOTS) { - LOGE("setBufferCount: bufferCount larger than slots available"); + ST_LOGE("setBufferCount: bufferCount larger than slots available"); return BAD_VALUE; } // Error out if the user has dequeued buffers for (int i=0 ; i<mBufferCount ; i++) { if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { - LOGE("setBufferCount: client owns some buffers"); + ST_LOGE("setBufferCount: client owns some buffers"); return -EINVAL; } } @@ -181,7 +199,7 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) { } if (bufferCount < minBufferSlots) { - LOGE("setBufferCount: requested buffer count (%d) is less than " + ST_LOGE("setBufferCount: requested buffer count (%d) is less than " "minimum (%d)", bufferCount, minBufferSlots); return BAD_VALUE; } @@ -200,7 +218,8 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) { status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) { if (!w || !h) { - LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", w, h); + ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", + w, h); return BAD_VALUE; } @@ -211,14 +230,14 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) } status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) { - LOGV("SurfaceTexture::requestBuffer"); + ST_LOGV("SurfaceTexture::requestBuffer"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("requestBuffer: SurfaceTexture has been abandoned!"); + ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!"); return NO_INIT; } if (slot < 0 || mBufferCount <= slot) { - LOGE("requestBuffer: slot index out of range [0, %d]: %d", + ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", mBufferCount, slot); return BAD_VALUE; } @@ -229,10 +248,10 @@ status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) { status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { - LOGV("SurfaceTexture::dequeueBuffer"); + ST_LOGV("SurfaceTexture::dequeueBuffer"); if ((w && !h) || (!w && h)) { - LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); + ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); return BAD_VALUE; } @@ -245,7 +264,7 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, bool tryAgain = true; while (tryAgain) { if (mAbandoned) { - LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); + ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -334,7 +353,8 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, // than allowed. const int avail = mBufferCount - (dequeuedCount+1); if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { - LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", + ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded " + "(dequeued=%d)", MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), dequeuedCount); return -EBUSY; @@ -391,7 +411,8 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, mGraphicBufferAlloc->createGraphicBuffer( w, h, format, usage, &error)); if (graphicBuffer == 0) { - LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); + ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer " + "failed"); return error; } if (updateFormat) { @@ -413,7 +434,7 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); + ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -441,29 +462,29 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { - LOGV("SurfaceTexture::queueBuffer"); + ST_LOGV("SurfaceTexture::queueBuffer"); sp<FrameAvailableListener> listener; { // scope for the lock Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("queueBuffer: SurfaceTexture has been abandoned!"); + ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!"); return NO_INIT; } if (buf < 0 || buf >= mBufferCount) { - LOGE("queueBuffer: slot index out of range [0, %d]: %d", + ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", mBufferCount, buf); return -EINVAL; } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", - buf, mSlots[buf].mBufferState); + ST_LOGE("queueBuffer: slot %d is not owned by the client " + "(state=%d)", buf, mSlots[buf].mBufferState); return -EINVAL; } else if (buf == mCurrentTexture) { - LOGE("queueBuffer: slot %d is current!", buf); + ST_LOGE("queueBuffer: slot %d is current!", buf); return -EINVAL; } else if (!mSlots[buf].mRequestBufferCalled) { - LOGE("queueBuffer: slot %d was enqueued without requesting a " + ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " "buffer", buf); return -EINVAL; } @@ -513,20 +534,20 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, } void SurfaceTexture::cancelBuffer(int buf) { - LOGV("SurfaceTexture::cancelBuffer"); + ST_LOGV("SurfaceTexture::cancelBuffer"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGW("cancelBuffer: SurfaceTexture has been abandoned!"); + ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!"); return; } if (buf < 0 || buf >= mBufferCount) { - LOGE("cancelBuffer: slot index out of range [0, %d]: %d", + ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount, buf); return; } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", + ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", buf, mSlots[buf].mBufferState); return; } @@ -535,10 +556,10 @@ void SurfaceTexture::cancelBuffer(int buf) { } status_t SurfaceTexture::setCrop(const Rect& crop) { - LOGV("SurfaceTexture::setCrop"); + ST_LOGV("SurfaceTexture::setCrop"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("setCrop: SurfaceTexture has been abandoned!"); + ST_LOGE("setCrop: SurfaceTexture has been abandoned!"); return NO_INIT; } mNextCrop = crop; @@ -546,10 +567,10 @@ status_t SurfaceTexture::setCrop(const Rect& crop) { } status_t SurfaceTexture::setTransform(uint32_t transform) { - LOGV("SurfaceTexture::setTransform"); + ST_LOGV("SurfaceTexture::setTransform"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("setTransform: SurfaceTexture has been abandoned!"); + ST_LOGE("setTransform: SurfaceTexture has been abandoned!"); return NO_INIT; } mNextTransform = transform; @@ -558,11 +579,11 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { status_t SurfaceTexture::connect(int api, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { - LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); + ST_LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("connect: SurfaceTexture has been abandoned!"); + ST_LOGE("connect: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -573,7 +594,7 @@ status_t SurfaceTexture::connect(int api, case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi != NO_CONNECTED_API) { - LOGE("connect: already connected (cur=%d, req=%d)", + ST_LOGE("connect: already connected (cur=%d, req=%d)", mConnectedApi, api); err = -EINVAL; } else { @@ -591,11 +612,11 @@ status_t SurfaceTexture::connect(int api, } status_t SurfaceTexture::disconnect(int api) { - LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); + ST_LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("disconnect: SurfaceTexture has been abandoned!"); + ST_LOGE("disconnect: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -613,7 +634,7 @@ status_t SurfaceTexture::disconnect(int api) { mNextTransform = 0; mDequeueCondition.signal(); } else { - LOGE("disconnect: connected to another api (cur=%d, req=%d)", + ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", mConnectedApi, api); err = -EINVAL; } @@ -626,7 +647,7 @@ status_t SurfaceTexture::disconnect(int api) { } status_t SurfaceTexture::setScalingMode(int mode) { - LOGV("SurfaceTexture::setScalingMode(%d)", mode); + ST_LOGV("SurfaceTexture::setScalingMode(%d)", mode); switch (mode) { case NATIVE_WINDOW_SCALING_MODE_FREEZE: @@ -642,11 +663,11 @@ status_t SurfaceTexture::setScalingMode(int mode) { } status_t SurfaceTexture::updateTexImage() { - LOGV("SurfaceTexture::updateTexImage"); + ST_LOGV("SurfaceTexture::updateTexImage"); Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("calling updateTexImage() on an abandoned SurfaceTexture"); + ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture"); return NO_INIT; } @@ -661,7 +682,7 @@ status_t SurfaceTexture::updateTexImage() { if (image == EGL_NO_IMAGE_KHR) { EGLDisplay dpy = eglGetCurrentDisplay(); if (mSlots[buf].mGraphicBuffer == 0) { - LOGE("buffer at slot %d is null", buf); + ST_LOGE("buffer at slot %d is null", buf); return BAD_VALUE; } image = createImage(dpy, mSlots[buf].mGraphicBuffer); @@ -676,15 +697,15 @@ status_t SurfaceTexture::updateTexImage() { GLint error; while ((error = glGetError()) != GL_NO_ERROR) { - LOGW("updateTexImage: clearing GL error: %#04x", error); + ST_LOGW("updateTexImage: clearing GL error: %#04x", error); } - glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image); + glBindTexture(mTexTarget, mTexName); + glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); bool failed = false; while ((error = glGetError()) != GL_NO_ERROR) { - LOGE("error binding external texture image %p (slot %d): %#04x", + ST_LOGE("error binding external texture image %p (slot %d): %#04x", image, buf, error); failed = true; } @@ -715,7 +736,7 @@ status_t SurfaceTexture::updateTexImage() { mDequeueCondition.signal(); } else { // We always bind the texture even if we don't update its contents. - glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName); + glBindTexture(mTexTarget, mTexName); } return OK; @@ -741,7 +762,7 @@ bool SurfaceTexture::isExternalFormat(uint32_t format) } GLenum SurfaceTexture::getCurrentTextureTarget() const { - return GL_TEXTURE_EXTERNAL_OES; + return mTexTarget; } void SurfaceTexture::getTransformMatrix(float mtx[16]) { @@ -750,7 +771,7 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) { } void SurfaceTexture::computeCurrentTransformMatrix() { - LOGV("SurfaceTexture::computeCurrentTransformMatrix"); + ST_LOGV("SurfaceTexture::computeCurrentTransformMatrix"); float xform[16]; for (int i = 0; i < 16; i++) { @@ -841,14 +862,14 @@ void SurfaceTexture::computeCurrentTransformMatrix() { } nsecs_t SurfaceTexture::getTimestamp() { - LOGV("SurfaceTexture::getTimestamp"); + ST_LOGV("SurfaceTexture::getTimestamp"); Mutex::Autolock lock(mMutex); return mCurrentTimestamp; } void SurfaceTexture::setFrameAvailableListener( const sp<FrameAvailableListener>& listener) { - LOGV("SurfaceTexture::setFrameAvailableListener"); + ST_LOGV("SurfaceTexture::setFrameAvailableListener"); Mutex::Autolock lock(mMutex); mFrameAvailableListener = listener; } @@ -892,11 +913,11 @@ status_t SurfaceTexture::drainQueueLocked() { while (mSynchronousMode && !mQueue.isEmpty()) { mDequeueCondition.wait(mMutex); if (mAbandoned) { - LOGE("drainQueueLocked: SurfaceTexture has been abandoned!"); + ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!"); return NO_INIT; } if (mConnectedApi == NO_CONNECTED_API) { - LOGE("drainQueueLocked: SurfaceTexture is not connected!"); + ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!"); return NO_INIT; } } @@ -926,7 +947,7 @@ EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); if (image == EGL_NO_IMAGE_KHR) { EGLint error = eglGetError(); - LOGE("error creating EGLImage: %#x", error); + ST_LOGE("error creating EGLImage: %#x", error); } return image; } @@ -956,7 +977,7 @@ int SurfaceTexture::query(int what, int* outValue) Mutex::Autolock lock(mMutex); if (mAbandoned) { - LOGE("query: SurfaceTexture has been abandoned!"); + ST_LOGE("query: SurfaceTexture has been abandoned!"); return NO_INIT; } @@ -991,6 +1012,10 @@ void SurfaceTexture::abandon() { mDequeueCondition.signal(); } +void SurfaceTexture::setName(const String8& name) { + mName = name; +} + void SurfaceTexture::dump(String8& result) const { char buffer[1024]; @@ -1004,8 +1029,8 @@ void SurfaceTexture::dump(String8& result, const char* prefix, snprintf(buffer, SIZE, "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " "mPixelFormat=%d, mTexName=%d\n", - prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight, - mPixelFormat, mTexName); + prefix, mBufferCount, mSynchronousMode, mDefaultWidth, + mDefaultHeight, mPixelFormat, mTexName); result.append(buffer); String8 fifo; @@ -1024,8 +1049,8 @@ void SurfaceTexture::dump(String8& result, const char* prefix, prefix, mCurrentCrop.left, mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, mCurrentTransform, mCurrentTexture, - prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom, - mNextTransform, fifoSize, fifo.string() + prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, + mNextCrop.bottom, mNextTransform, fifoSize, fifo.string() ); result.append(buffer); @@ -1048,8 +1073,8 @@ void SurfaceTexture::dump(String8& result, const char* prefix, "transform=0x%02x, timestamp=%lld", prefix, (i==mCurrentTexture)?">":" ", i, stateName(slot.mBufferState), - slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, slot.mCrop.bottom, - slot.mTransform, slot.mTimestamp + slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, + slot.mCrop.bottom, slot.mTransform, slot.mTimestamp ); result.append(buffer); @@ -1057,7 +1082,8 @@ void SurfaceTexture::dump(String8& result, const char* prefix, if (buf != NULL) { snprintf(buffer, SIZE, ", %p [%4ux%4u:%4u,%3X]", - buf->handle, buf->width, buf->height, buf->stride, buf->format); + buf->handle, buf->width, buf->height, buf->stride, + buf->format); result.append(buffer); } result.append("\n"); diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h index 28dba13dec35..e2bdde1eca89 100644 --- a/libs/hwui/TextDropShadowCache.h +++ b/libs/hwui/TextDropShadowCache.h @@ -81,7 +81,7 @@ struct ShadowText { LTE_INT(flags) { LTE_INT(italicStyle) { LTE_INT(scaleX) { - return strncmp16(text, rhs.text, len >> 1) < 0; + return memcmp(text, rhs.text, len) < 0; } } } diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index f27758249a5d..20b1f52104da 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -329,10 +329,7 @@ ProgramStoreCreate { ProgramRasterCreate { direct - param bool pointSmooth - param bool lineSmooth param bool pointSprite - param float lineWidth param RsCullMode cull ret RsProgramRaster } diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp index 945b5eca68fd..94bfe4275abe 100644 --- a/libs/rs/rsProgramRaster.cpp +++ b/libs/rs/rsProgramRaster.cpp @@ -21,19 +21,12 @@ using namespace android; using namespace android::renderscript; -ProgramRaster::ProgramRaster(Context *rsc, bool pointSmooth, - bool lineSmooth, bool pointSprite, - float lineWidth, RsCullMode cull) +ProgramRaster::ProgramRaster(Context *rsc, bool pointSprite, RsCullMode cull) : ProgramBase(rsc) { memset(&mHal, 0, sizeof(mHal)); - - mHal.state.pointSmooth = pointSmooth; - mHal.state.lineSmooth = lineSmooth; mHal.state.pointSprite = pointSprite; - mHal.state.lineWidth = lineWidth; mHal.state.cull = cull; - rsc->mHal.funcs.raster.init(rsc, this); } @@ -74,8 +67,7 @@ ProgramRasterState::~ProgramRasterState() { } void ProgramRasterState::init(Context *rsc) { - mDefault.set(ProgramRaster::getProgramRaster(rsc, false, false, - false, 1.f, RS_CULL_BACK).get()); + mDefault.set(ProgramRaster::getProgramRaster(rsc, false, RS_CULL_BACK).get()); } void ProgramRasterState::deinit(Context *rsc) { @@ -84,19 +76,13 @@ void ProgramRasterState::deinit(Context *rsc) { } ObjectBaseRef<ProgramRaster> ProgramRaster::getProgramRaster(Context *rsc, - bool pointSmooth, - bool lineSmooth, bool pointSprite, - float lineWidth, RsCullMode cull) { ObjectBaseRef<ProgramRaster> returnRef; ObjectBase::asyncLock(); for (uint32_t ct = 0; ct < rsc->mStateRaster.mRasterPrograms.size(); ct++) { ProgramRaster *existing = rsc->mStateRaster.mRasterPrograms[ct]; - if (existing->mHal.state.pointSmooth != pointSmooth) continue; - if (existing->mHal.state.lineSmooth != lineSmooth) continue; if (existing->mHal.state.pointSprite != pointSprite) continue; - if (existing->mHal.state.lineWidth != lineWidth) continue; if (existing->mHal.state.cull != cull) continue; returnRef.set(existing); ObjectBase::asyncUnlock(); @@ -104,8 +90,7 @@ ObjectBaseRef<ProgramRaster> ProgramRaster::getProgramRaster(Context *rsc, } ObjectBase::asyncUnlock(); - ProgramRaster *pr = new ProgramRaster(rsc, pointSmooth, - lineSmooth, pointSprite, lineWidth, cull); + ProgramRaster *pr = new ProgramRaster(rsc, pointSprite, cull); returnRef.set(pr); ObjectBase::asyncLock(); @@ -118,10 +103,8 @@ ObjectBaseRef<ProgramRaster> ProgramRaster::getProgramRaster(Context *rsc, namespace android { namespace renderscript { -RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, bool pointSmooth, bool lineSmooth, - bool pointSprite, float lineWidth, RsCullMode cull) { - ObjectBaseRef<ProgramRaster> pr = ProgramRaster::getProgramRaster(rsc, pointSmooth, lineSmooth, - pointSprite, lineWidth, cull); +RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, bool pointSprite, RsCullMode cull) { + ObjectBaseRef<ProgramRaster> pr = ProgramRaster::getProgramRaster(rsc, pointSprite, cull); pr->incUserRef(); return pr.get(); } diff --git a/libs/rs/rsProgramRaster.h b/libs/rs/rsProgramRaster.h index 09d7d5432c9a..20af30a1b90b 100644 --- a/libs/rs/rsProgramRaster.h +++ b/libs/rs/rsProgramRaster.h @@ -33,19 +33,13 @@ public: static ProgramRaster *createFromStream(Context *rsc, IStream *stream); static ObjectBaseRef<ProgramRaster> getProgramRaster(Context *rsc, - bool pointSmooth, - bool lineSmooth, bool pointSprite, - float lineWidth, RsCullMode cull); struct Hal { mutable void *drv; struct State { - bool pointSmooth; - bool lineSmooth; bool pointSprite; - float lineWidth; RsCullMode cull; }; State state; @@ -58,10 +52,7 @@ protected: private: ProgramRaster(Context *rsc, - bool pointSmooth, - bool lineSmooth, bool pointSprite, - float lineWidth, RsCullMode cull); }; diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 8dab291b3c24..565608889d28 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -482,6 +482,7 @@ void Region::boolean_operation(int op, Region& dst, if (!rhs.isValid()) { LOGE("Region::boolean_operation(op=%d) invalid Rect={%d,%d,%d,%d}", op, rhs.left, rhs.top, rhs.right, rhs.bottom); + return; } #if VALIDATE_WITH_CORECG || VALIDATE_REGIONS diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index e4eadbd0046d..638f72f0b66a 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -100,12 +100,8 @@ LOCAL_LDLIBS += -lpthread LOCAL_SHARED_LIBRARIES := \ libz \ liblog \ - libcutils - -ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86) -# This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp -LOCAL_SHARED_LIBRARIES += libdl -endif # linux-x86 + libcutils \ + libdl LOCAL_MODULE:= libutils include $(BUILD_SHARED_LIBRARY) diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 8895c9e7348c..4f4f9297e614 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -2958,7 +2958,7 @@ public class AudioService extends IAudioService.Stub { Log.w(TAG, " RemoteControlClient died"); // remote control client died, make sure the displays don't use it anymore // by setting its remote control client to null - registerRemoteControlClient(mMediaIntent, null, null/*ignored*/); + registerRemoteControlClient(mMediaIntent, null/*rcClient*/, null/*ignored*/); } public IBinder getBinder() { @@ -3366,7 +3366,12 @@ public class AudioService extends IAudioService.Stub { } } - /** see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...) */ + /** + * see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...) + * Note: using this method with rcClient == null is a way to "disable" the IRemoteControlClient + * without modifying the RC stack, but while still causing the display to refresh (will + * become blank as a result of this) + */ public void registerRemoteControlClient(PendingIntent mediaIntent, IRemoteControlClient rcClient, String callingPackageName) { if (DEBUG_RC) Log.i(TAG, "Register remote control client rcClient="+rcClient); @@ -3384,6 +3389,15 @@ public class AudioService extends IAudioService.Stub { } // save the new remote control client rcse.mRcClient = rcClient; + rcse.mCallingPackageName = callingPackageName; + rcse.mCallingUid = Binder.getCallingUid(); + if (rcClient == null) { + rcse.mRcClientDeathHandler = null; + break; + } + + // there is a new (non-null) client: + // 1/ give the new client the current display (if any) if (mRcDisplay != null) { try { rcse.mRcClient.plugRemoteControlDisplay(mRcDisplay); @@ -3392,14 +3406,8 @@ public class AudioService extends IAudioService.Stub { e.printStackTrace(); } } - rcse.mCallingPackageName = callingPackageName; - rcse.mCallingUid = Binder.getCallingUid(); - if (rcClient == null) { - rcse.mRcClientDeathHandler = null; - break; - } - // monitor the new client's death - IBinder b = rcClient.asBinder(); + // 2/ monitor the new client's death + IBinder b = rcse.mRcClient.asBinder(); RcClientDeathHandler rcdh = new RcClientDeathHandler(b, rcse.mMediaIntent); try { diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java index 0ce35269bf39..f16ba368d443 100644 --- a/media/java/android/media/Ringtone.java +++ b/media/java/android/media/Ringtone.java @@ -166,6 +166,9 @@ public class Ringtone { } private void openMediaPlayer() throws IOException { + if (mAudio != null) { + mAudio.release(); + } mAudio = new MediaPlayer(); if (mUri != null) { mAudio.setDataSource(mContext, mUri); @@ -203,7 +206,7 @@ public class Ringtone { mUri = uri; openMediaPlayer(); } - + /** * Plays the ringtone. */ diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index c270f21a7b25..f3174fef2666 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -651,6 +651,10 @@ static void android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz) { LOGV("native_finalize"); + sp<MediaPlayer> mp = getMediaPlayer(env, thiz); + if (mp != NULL) { + LOGW("MediaPlayer finalized without being released"); + } android_media_MediaPlayer_release(env, thiz); } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 0386d4b65987..b5eef94a4c00 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -52,6 +52,7 @@ #include <media/Metadata.h> #include <media/AudioTrack.h> #include <media/MemoryLeakTrackUtil.h> +#include <media/stagefright/MediaErrors.h> #include <system/audio.h> @@ -1132,7 +1133,11 @@ sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, i player->start(); LOGV("wait for playback complete"); - if (cache->wait() != NO_ERROR) goto Exit; + cache->wait(); + // in case of error, return what was successfully decoded. + if (cache->size() == 0) { + goto Exit; + } mem = new MemoryBase(cache->getHeap(), 0, cache->size()); *pSampleRate = cache->sampleRate(); @@ -1175,7 +1180,11 @@ sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, u player->start(); LOGV("wait for playback complete"); - if (cache->wait() != NO_ERROR) goto Exit; + cache->wait(); + // in case of error, return what was successfully decoded. + if (cache->size() == 0) { + goto Exit; + } mem = new MemoryBase(cache->getHeap(), 0, cache->size()); *pSampleRate = cache->sampleRate(); diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp index 605d056f3504..079f6fa01952 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp @@ -41,7 +41,7 @@ NuPlayer::HTTPLiveSource::HTTPLiveSource( mUIDValid(uidValid), mUID(uid), mFlags(0), - mEOS(false), + mFinalResult(OK), mOffset(0) { if (headers) { mExtraHeaders = *headers; @@ -95,9 +95,9 @@ sp<MetaData> NuPlayer::HTTPLiveSource::getFormat(bool audio) { return source->getFormat(); } -bool NuPlayer::HTTPLiveSource::feedMoreTSData() { - if (mEOS) { - return false; +status_t NuPlayer::HTTPLiveSource::feedMoreTSData() { + if (mFinalResult != OK) { + return mFinalResult; } sp<LiveDataSource> source = @@ -110,9 +110,13 @@ bool NuPlayer::HTTPLiveSource::feedMoreTSData() { if (n == -EWOULDBLOCK) { break; } else if (n < 0) { - LOGI("input data EOS reached."); + if (n != ERROR_END_OF_STREAM) { + LOGI("input data EOS reached, error %ld", n); + } else { + LOGI("input data EOS reached."); + } mTSParser->signalEOS(n); - mEOS = true; + mFinalResult = n; break; } else { if (buffer[0] == 0x00) { @@ -129,7 +133,7 @@ bool NuPlayer::HTTPLiveSource::feedMoreTSData() { if (err != OK) { LOGE("TS Parser returned error %d", err); mTSParser->signalEOS(err); - mEOS = true; + mFinalResult = err; break; } } @@ -138,7 +142,7 @@ bool NuPlayer::HTTPLiveSource::feedMoreTSData() { } } - return true; + return OK; } status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit( @@ -168,7 +172,7 @@ status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) { status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) { // We need to make sure we're not seeking until we have seen the very first // PTS timestamp in the whole stream (from the beginning of the stream). - while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData()) { + while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData() == OK) { usleep(100000); } diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h index 36c67c501b38..f22af5bee607 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h @@ -35,8 +35,7 @@ struct NuPlayer::HTTPLiveSource : public NuPlayer::Source { virtual void start(); - // Returns true iff more data was available, false on EOS. - virtual bool feedMoreTSData(); + virtual status_t feedMoreTSData(); virtual sp<MetaData> getFormat(bool audio); virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit); @@ -59,7 +58,7 @@ private: bool mUIDValid; uid_t mUID; uint32_t mFlags; - bool mEOS; + status_t mFinalResult; off64_t mOffset; sp<ALooper> mLiveLooper; sp<LiveSession> mLiveSession; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 7218fafdc684..6b40528a160f 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -235,11 +235,17 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { instantiateDecoder(true, &mAudioDecoder); } - if (!mSource->feedMoreTSData()) { + status_t err; + if ((err = mSource->feedMoreTSData()) != OK) { if (mAudioDecoder == NULL && mVideoDecoder == NULL) { // We're not currently decoding anything (no audio or // video tracks found) and we just ran out of input data. - notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); + + if (err == ERROR_END_OF_STREAM) { + notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); + } else { + notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); + } } break; } @@ -267,12 +273,23 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { audio, codecRequest); if (err == -EWOULDBLOCK) { - if (mSource->feedMoreTSData()) { + if (mSource->feedMoreTSData() == OK) { msg->post(); } } } else if (what == ACodec::kWhatEOS) { - mRenderer->queueEOS(audio, ERROR_END_OF_STREAM); + int32_t err; + CHECK(codecRequest->findInt32("err", &err)); + + if (err == ERROR_END_OF_STREAM) { + LOGV("got %s decoder EOS", audio ? "audio" : "video"); + } else { + LOGV("got %s decoder EOS w/ error %d", + audio ? "audio" : "video", + err); + } + + mRenderer->queueEOS(audio, err); } else if (what == ACodec::kWhatFlushCompleted) { bool needShutdown; @@ -397,7 +414,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { if (finalResult == ERROR_END_OF_STREAM) { LOGV("reached %s EOS", audio ? "audio" : "video"); } else { - LOGE("%s track encountered an error (0x%08x)", + LOGE("%s track encountered an error (%d)", audio ? "audio" : "video", finalResult); notifyListener( diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h index 5e55487ae88a..8a7eece12050 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h @@ -29,8 +29,9 @@ struct NuPlayer::Source : public RefBase { virtual void start() = 0; - // Returns true iff more data was available, false on EOS. - virtual bool feedMoreTSData() = 0; + // Returns OK iff more data was available, + // an error or ERROR_END_OF_STREAM if not. + virtual status_t feedMoreTSData() = 0; virtual sp<MetaData> getFormat(bool audio) = 0; diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp index 7319e4ceb585..f79565425665 100644 --- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp +++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp @@ -34,7 +34,7 @@ namespace android { NuPlayer::StreamingSource::StreamingSource(const sp<IStreamSource> &source) : mSource(source), - mEOS(false) { + mFinalResult(OK) { } NuPlayer::StreamingSource::~StreamingSource() { @@ -47,9 +47,9 @@ void NuPlayer::StreamingSource::start() { mStreamListener->start(); } -bool NuPlayer::StreamingSource::feedMoreTSData() { - if (mEOS) { - return false; +status_t NuPlayer::StreamingSource::feedMoreTSData() { + if (mFinalResult != OK) { + return mFinalResult; } for (int32_t i = 0; i < 50; ++i) { @@ -60,7 +60,7 @@ bool NuPlayer::StreamingSource::feedMoreTSData() { if (n == 0) { LOGI("input data EOS reached."); mTSParser->signalEOS(ERROR_END_OF_STREAM); - mEOS = true; + mFinalResult = ERROR_END_OF_STREAM; break; } else if (n == INFO_DISCONTINUITY) { ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK; @@ -92,14 +92,14 @@ bool NuPlayer::StreamingSource::feedMoreTSData() { LOGE("TS Parser returned error %d", err); mTSParser->signalEOS(err); - mEOS = true; + mFinalResult = err; break; } } } } - return true; + return OK; } sp<MetaData> NuPlayer::StreamingSource::getFormat(bool audio) { diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h index 7abce84746cc..ca00ef91d2d9 100644 --- a/media/libmediaplayerservice/nuplayer/StreamingSource.h +++ b/media/libmediaplayerservice/nuplayer/StreamingSource.h @@ -31,8 +31,7 @@ struct NuPlayer::StreamingSource : public NuPlayer::Source { virtual void start(); - // Returns true iff more data was available, false on EOS. - virtual bool feedMoreTSData(); + virtual status_t feedMoreTSData(); virtual sp<MetaData> getFormat(bool audio); virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit); @@ -42,7 +41,7 @@ protected: private: sp<IStreamSource> mSource; - bool mEOS; + status_t mFinalResult; sp<NuPlayerStreamListener> mStreamListener; sp<ATSParser> mTSParser; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index a2d9e5910c37..9cb18de26e24 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -323,6 +323,7 @@ ACodec::ACodec() mFlushingState = new FlushingState(this); mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; + mInputEOSResult = OK; changeState(mUninitializedState); } @@ -686,6 +687,8 @@ void ACodec::setComponentRole( "audio_decoder.amrwb", "audio_encoder.amrwb" }, { MEDIA_MIMETYPE_AUDIO_AAC, "audio_decoder.aac", "audio_encoder.aac" }, + { MEDIA_MIMETYPE_AUDIO_VORBIS, + "audio_decoder.vorbis", "audio_encoder.vorbis" }, { MEDIA_MIMETYPE_VIDEO_AVC, "video_decoder.avc", "video_encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, @@ -749,9 +752,19 @@ void ACodec::configureCodec( CHECK(msg->findInt32("sample-rate", &sampleRate)); CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK); - } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { - } else { - TRESPASS(); + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { + CHECK_EQ(setupAMRDecoder(false /* isWAMR */), (status_t)OK); + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { + CHECK_EQ(setupAMRDecoder(true /* isWAMR */), (status_t)OK); + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) + || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { + // These are PCM-like formats with a fixed sample rate but + // a variable number of channels. + + int32_t numChannels; + CHECK(msg->findInt32("channel-count", &numChannels)); + + CHECK_EQ(setupG711Decoder(numChannels), (status_t)OK); } int32_t maxInputSize; @@ -823,6 +836,84 @@ status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) { return err; } +status_t ACodec::setupAMRDecoder(bool isWAMR) { + OMX_AUDIO_PARAM_AMRTYPE def; + InitOMXParams(&def); + def.nPortIndex = kPortIndexInput; + + status_t err = + mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; + + def.eAMRBandMode = + isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0; + + return mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); +} + +status_t ACodec::setupG711Decoder(int32_t numChannels) { + return setupRawAudioFormat( + kPortIndexInput, 8000 /* sampleRate */, numChannels); +} + +status_t ACodec::setupRawAudioFormat( + OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = portIndex; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + + err = mOMX->setParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; + InitOMXParams(&pcmParams); + pcmParams.nPortIndex = portIndex; + + err = mOMX->getParameter( + mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); + + if (err != OK) { + return err; + } + + pcmParams.nChannels = numChannels; + pcmParams.eNumData = OMX_NumericalDataSigned; + pcmParams.bInterleaved = OMX_TRUE; + pcmParams.nBitPerSample = 16; + pcmParams.nSamplingRate = sampleRate; + pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; + + if (numChannels == 1) { + pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF; + } else { + CHECK_EQ(numChannels, 2); + + pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF; + pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF; + } + + return mOMX->setParameter( + mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); +} + status_t ACodec::setVideoPortFormatType( OMX_U32 portIndex, OMX_VIDEO_CODINGTYPE compressionFormat, @@ -1347,7 +1438,10 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { case KEEP_BUFFERS: { if (buffer == NULL) { - mCodec->mPortEOS[kPortIndexInput] = true; + if (!mCodec->mPortEOS[kPortIndexInput]) { + mCodec->mPortEOS[kPortIndexInput] = true; + mCodec->mInputEOSResult = err; + } } break; } @@ -1398,8 +1492,14 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { getMoreInputDataIfPossible(); } else if (!mCodec->mPortEOS[kPortIndexInput]) { - LOGV("[%s] Signalling EOS on the input port", - mCodec->mComponentName.c_str()); + if (err != ERROR_END_OF_STREAM) { + LOGV("[%s] Signalling EOS on the input port " + "due to error %d", + mCodec->mComponentName.c_str(), err); + } else { + LOGV("[%s] Signalling EOS on the input port", + mCodec->mComponentName.c_str()); + } LOGV("[%s] calling emptyBuffer %p signalling EOS", mCodec->mComponentName.c_str(), bufferID); @@ -1416,6 +1516,7 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { info->mStatus = BufferInfo::OWNED_BY_COMPONENT; mCodec->mPortEOS[kPortIndexInput] = true; + mCodec->mInputEOSResult = err; } break; @@ -1523,6 +1624,7 @@ bool ACodec::BaseState::onOMXFillBufferDone( if (flags & OMX_BUFFERFLAG_EOS) { sp<AMessage> notify = mCodec->mNotify->dup(); notify->setInt32("what", ACodec::kWhatEOS); + notify->setInt32("err", mCodec->mInputEOSResult); notify->post(); mCodec->mPortEOS[kPortIndexOutput] = true; @@ -1721,6 +1823,8 @@ void ACodec::UninitializedState::onSetup( mCodec->mPortEOS[kPortIndexInput] = mCodec->mPortEOS[kPortIndexOutput] = false; + mCodec->mInputEOSResult = OK; + mCodec->configureCodec(mime.c_str(), msg); sp<RefBase> obj; @@ -2371,6 +2475,8 @@ void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { mCodec->mPortEOS[kPortIndexInput] = mCodec->mPortEOS[kPortIndexOutput] = false; + mCodec->mInputEOSResult = OK; + mCodec->changeState(mCodec->mExecutingState); } } diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp index 4e464148b090..0be2ca40153d 100644 --- a/media/libstagefright/AVIExtractor.cpp +++ b/media/libstagefright/AVIExtractor.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "AVIExtractor" #include <utils/Log.h> +#include "include/avc_utils.h" #include "include/AVIExtractor.h" #include <binder/ProcessState.h> @@ -55,11 +56,36 @@ private: MediaBufferGroup *mBufferGroup; size_t mSampleIndex; + sp<MP3Splitter> mSplitter; + DISALLOW_EVIL_CONSTRUCTORS(AVISource); }; //////////////////////////////////////////////////////////////////////////////// +struct AVIExtractor::MP3Splitter : public RefBase { + MP3Splitter(); + + void clear(); + void append(MediaBuffer *buffer); + status_t read(MediaBuffer **buffer); + +protected: + virtual ~MP3Splitter(); + +private: + bool mFindSync; + int64_t mBaseTimeUs; + int64_t mNumSamplesRead; + sp<ABuffer> mBuffer; + + bool resync(); + + DISALLOW_EVIL_CONSTRUCTORS(MP3Splitter); +}; + +//////////////////////////////////////////////////////////////////////////////// + AVIExtractor::AVISource::AVISource( const sp<AVIExtractor> &extractor, size_t trackIndex) : mExtractor(extractor), @@ -83,6 +109,15 @@ status_t AVIExtractor::AVISource::start(MetaData *params) { mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); mSampleIndex = 0; + const char *mime; + CHECK(mTrack.mMeta->findCString(kKeyMIMEType, &mime)); + + if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { + mSplitter = new MP3Splitter; + } else { + mSplitter.clear(); + } + return OK; } @@ -92,6 +127,8 @@ status_t AVIExtractor::AVISource::stop() { delete mBufferGroup; mBufferGroup = NULL; + mSplitter.clear(); + return OK; } @@ -115,39 +152,213 @@ status_t AVIExtractor::AVISource::read( if (err != OK) { return ERROR_END_OF_STREAM; } + + if (mSplitter != NULL) { + mSplitter->clear(); + } } - off64_t offset; - size_t size; - bool isKey; - int64_t timeUs; - status_t err = mExtractor->getSampleInfo( - mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs); + for (;;) { + if (mSplitter != NULL) { + status_t err = mSplitter->read(buffer); + + if (err == OK) { + break; + } else if (err != -EAGAIN) { + return err; + } + } + + off64_t offset; + size_t size; + bool isKey; + int64_t timeUs; + status_t err = mExtractor->getSampleInfo( + mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs); - ++mSampleIndex; + ++mSampleIndex; - if (err != OK) { - return ERROR_END_OF_STREAM; + if (err != OK) { + return ERROR_END_OF_STREAM; + } + + MediaBuffer *out; + CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK); + + ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size); + + if (n < (ssize_t)size) { + return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; + } + + out->set_range(0, size); + + out->meta_data()->setInt64(kKeyTime, timeUs); + + if (isKey) { + out->meta_data()->setInt32(kKeyIsSyncFrame, 1); + } + + if (mSplitter == NULL) { + *buffer = out; + break; + } + + mSplitter->append(out); + out->release(); + out = NULL; } - MediaBuffer *out; - CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK); + return OK; +} - ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size); +//////////////////////////////////////////////////////////////////////////////// - if (n < (ssize_t)size) { - return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; +AVIExtractor::MP3Splitter::MP3Splitter() + : mFindSync(true), + mBaseTimeUs(-1ll), + mNumSamplesRead(0) { +} + +AVIExtractor::MP3Splitter::~MP3Splitter() { +} + +void AVIExtractor::MP3Splitter::clear() { + mFindSync = true; + mBaseTimeUs = -1ll; + mNumSamplesRead = 0; + + if (mBuffer != NULL) { + mBuffer->setRange(0, 0); + } +} + +void AVIExtractor::MP3Splitter::append(MediaBuffer *buffer) { + size_t prevCapacity = (mBuffer != NULL) ? mBuffer->capacity() : 0; + + if (mBaseTimeUs < 0) { + CHECK(mBuffer == NULL || mBuffer->size() == 0); + CHECK(buffer->meta_data()->findInt64(kKeyTime, &mBaseTimeUs)); + mNumSamplesRead = 0; + } + + if (mBuffer != NULL && mBuffer->offset() > 0) { + memmove(mBuffer->base(), mBuffer->data(), mBuffer->size()); + mBuffer->setRange(0, mBuffer->size()); + } + + if (mBuffer == NULL + || mBuffer->size() + buffer->range_length() > prevCapacity) { + size_t newCapacity = + (prevCapacity + buffer->range_length() + 1023) & ~1023; + + sp<ABuffer> newBuffer = new ABuffer(newCapacity); + if (mBuffer != NULL) { + memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size()); + newBuffer->setRange(0, mBuffer->size()); + } else { + newBuffer->setRange(0, 0); + } + mBuffer = newBuffer; + } + + memcpy(mBuffer->data() + mBuffer->size(), + (const uint8_t *)buffer->data() + buffer->range_offset(), + buffer->range_length()); + + mBuffer->setRange(0, mBuffer->size() + buffer->range_length()); +} + +bool AVIExtractor::MP3Splitter::resync() { + if (mBuffer == NULL) { + return false; } - out->set_range(0, size); + bool foundSync = false; + for (size_t offset = 0; offset + 3 < mBuffer->size(); ++offset) { + uint32_t firstHeader = U32_AT(mBuffer->data() + offset); + + size_t frameSize; + if (!GetMPEGAudioFrameSize(firstHeader, &frameSize)) { + continue; + } + + size_t subsequentOffset = offset + frameSize; + size_t i = 3; + while (i > 0) { + if (subsequentOffset + 3 >= mBuffer->size()) { + break; + } + + static const uint32_t kMask = 0xfffe0c00; + + uint32_t header = U32_AT(mBuffer->data() + subsequentOffset); + if ((header & kMask) != (firstHeader & kMask)) { + break; + } + + if (!GetMPEGAudioFrameSize(header, &frameSize)) { + break; + } + + subsequentOffset += frameSize; + --i; + } - out->meta_data()->setInt64(kKeyTime, timeUs); + if (i == 0) { + foundSync = true; + memmove(mBuffer->data(), + mBuffer->data() + offset, + mBuffer->size() - offset); - if (isKey) { - out->meta_data()->setInt32(kKeyIsSyncFrame, 1); + mBuffer->setRange(0, mBuffer->size() - offset); + break; + } } - *buffer = out; + return foundSync; +} + +status_t AVIExtractor::MP3Splitter::read(MediaBuffer **out) { + *out = NULL; + + if (mFindSync) { + if (!resync()) { + return -EAGAIN; + } + + mFindSync = false; + } + + if (mBuffer->size() < 4) { + return -EAGAIN; + } + + uint32_t header = U32_AT(mBuffer->data()); + size_t frameSize; + int sampleRate; + int numSamples; + if (!GetMPEGAudioFrameSize( + header, &frameSize, &sampleRate, NULL, NULL, &numSamples)) { + return ERROR_MALFORMED; + } + + if (mBuffer->size() < frameSize) { + return -EAGAIN; + } + + MediaBuffer *mbuf = new MediaBuffer(frameSize); + memcpy(mbuf->data(), mBuffer->data(), frameSize); + + int64_t timeUs = mBaseTimeUs + (mNumSamplesRead * 1000000ll) / sampleRate; + mNumSamplesRead += numSamples; + + mbuf->meta_data()->setInt64(kKeyTime, timeUs); + + mBuffer->setRange( + mBuffer->offset() + frameSize, mBuffer->size() - frameSize); + + *out = mbuf; return OK; } @@ -362,6 +573,13 @@ static const char *GetMIMETypeForHandler(uint32_t handler) { case FOURCC('X', 'V', 'I', 'X'): return MEDIA_MIMETYPE_VIDEO_MPEG4; + // from http://wiki.multimedia.cx/index.php?title=H264 + case FOURCC('a', 'v', 'c', '1'): + case FOURCC('d', 'a', 'v', 'c'): + case FOURCC('x', '2', '6', '4'): + case FOURCC('v', 's', 's', 'h'): + return MEDIA_MIMETYPE_VIDEO_AVC; + default: return NULL; } @@ -406,6 +624,14 @@ status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) { return ERROR_MALFORMED; } + if (mime == NULL) { + LOGW("Unsupported video format '%c%c%c%c'", + (char)(handler >> 24), + (char)((handler >> 16) & 0xff), + (char)((handler >> 8) & 0xff), + (char)(handler & 0xff)); + } + kind = Track::VIDEO; } else if (type == FOURCC('a', 'u', 'd', 's')) { if (mime && strncasecmp(mime, "audio/", 6)) { @@ -433,6 +659,8 @@ status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) { track->mThumbnailSampleSize = 0; track->mThumbnailSampleIndex = -1; track->mMaxSampleSize = 0; + track->mAvgChunkSize = 1.0; + track->mFirstChunkSize = 0; return OK; } @@ -451,8 +679,8 @@ status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) { bool isVideo = (track->mKind == Track::VIDEO); - if ((isVideo && size < 40) || (!isVideo && size < 18)) { - // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively. + if ((isVideo && size < 40) || (!isVideo && size < 16)) { + // Expected a BITMAPINFO or WAVEFORMAT(EX) structure, respectively. return ERROR_MALFORMED; } @@ -473,8 +701,11 @@ status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) { track->mMeta->setInt32(kKeyHeight, height); } else { uint32_t format = U16LE_AT(data); + if (format == 0x55) { track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); + } else { + LOGW("Unsupported audio format = 0x%04x", format); } uint32_t numChannels = U16LE_AT(&data[2]); @@ -632,6 +863,47 @@ status_t AVIExtractor::parseIndex(off64_t offset, size_t size) { for (size_t i = 0; i < mTracks.size(); ++i) { Track *track = &mTracks.editItemAt(i); + if (track->mBytesPerSample > 0) { + // Assume all chunks are roughly the same size for now. + + // Compute the avg. size of the first 128 chunks (if there are + // that many), but exclude the size of the first one, since + // it may be an outlier. + size_t numSamplesToAverage = track->mSamples.size(); + if (numSamplesToAverage > 256) { + numSamplesToAverage = 256; + } + + double avgChunkSize = 0; + size_t j; + for (j = 0; j <= numSamplesToAverage; ++j) { + off64_t offset; + size_t size; + bool isKey; + int64_t dummy; + + status_t err = + getSampleInfo( + i, j, + &offset, &size, &isKey, &dummy); + + if (err != OK) { + return err; + } + + if (j == 0) { + track->mFirstChunkSize = size; + continue; + } + + avgChunkSize += size; + } + + avgChunkSize /= numSamplesToAverage; + + track->mAvgChunkSize = avgChunkSize; + } + int64_t durationUs; CHECK_EQ((status_t)OK, getSampleTime(i, track->mSamples.size() - 1, &durationUs)); @@ -646,37 +918,27 @@ status_t AVIExtractor::parseIndex(off64_t offset, size_t size) { AString mime = tmp; - if (!strncasecmp("video/", mime.c_str(), 6) - && track->mThumbnailSampleIndex >= 0) { - int64_t thumbnailTimeUs; - CHECK_EQ((status_t)OK, - getSampleTime(i, track->mThumbnailSampleIndex, - &thumbnailTimeUs)); + if (!strncasecmp("video/", mime.c_str(), 6)) { + if (track->mThumbnailSampleIndex >= 0) { + int64_t thumbnailTimeUs; + CHECK_EQ((status_t)OK, + getSampleTime(i, track->mThumbnailSampleIndex, + &thumbnailTimeUs)); - track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); - - if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) { - status_t err = addMPEG4CodecSpecificData(i); - - if (err != OK) { - return err; - } + track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); } - } - if (track->mBytesPerSample != 0) { - // Assume all chunks are the same size for now. + status_t err = OK; - off64_t offset; - size_t size; - bool isKey; - int64_t sampleTimeUs; - CHECK_EQ((status_t)OK, - getSampleInfo( - i, 0, - &offset, &size, &isKey, &sampleTimeUs)); + if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) { + err = addMPEG4CodecSpecificData(i); + } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { + err = addH264CodecSpecificData(i); + } - track->mRate *= size / track->mBytesPerSample; + if (err != OK) { + return err; + } } } @@ -781,6 +1043,63 @@ status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) { return OK; } +status_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) { + Track *track = &mTracks.editItemAt(trackIndex); + + off64_t offset; + size_t size; + bool isKey; + int64_t timeUs; + + // Extract codec specific data from the first non-empty sample. + + size_t sampleIndex = 0; + for (;;) { + status_t err = + getSampleInfo( + trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs); + + if (err != OK) { + return err; + } + + if (size > 0) { + break; + } + + ++sampleIndex; + } + + sp<ABuffer> buffer = new ABuffer(size); + ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); + + if (n < (ssize_t)size) { + return n < 0 ? (status_t)n : ERROR_MALFORMED; + } + + sp<MetaData> meta = MakeAVCCodecSpecificData(buffer); + + if (meta == NULL) { + LOGE("Unable to extract AVC codec specific data"); + return ERROR_MALFORMED; + } + + int32_t width, height; + CHECK(meta->findInt32(kKeyWidth, &width)); + CHECK(meta->findInt32(kKeyHeight, &height)); + + uint32_t type; + const void *csd; + size_t csdSize; + CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize)); + + track->mMeta->setInt32(kKeyWidth, width); + track->mMeta->setInt32(kKeyHeight, width); + track->mMeta->setData(kKeyAVCC, type, csd, csdSize); + + return OK; +} + status_t AVIExtractor::getSampleInfo( size_t trackIndex, size_t sampleIndex, off64_t *offset, size_t *size, bool *isKey, @@ -823,6 +1142,18 @@ status_t AVIExtractor::getSampleInfo( *isKey = info.mIsKey; + if (track.mBytesPerSample > 0) { + size_t sampleStartInBytes; + if (sampleIndex == 0) { + sampleStartInBytes = 0; + } else { + sampleStartInBytes = + track.mFirstChunkSize + track.mAvgChunkSize * (sampleIndex - 1); + } + + sampleIndex = sampleStartInBytes / track.mBytesPerSample; + } + *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale; return OK; @@ -847,8 +1178,24 @@ status_t AVIExtractor::getSampleIndexAtTime( const Track &track = mTracks.itemAt(trackIndex); - ssize_t closestSampleIndex = - timeUs / track.mRate * track.mScale / 1000000ll; + ssize_t closestSampleIndex; + + if (track.mBytesPerSample > 0) { + size_t closestByteOffset = + (timeUs * track.mBytesPerSample) + / track.mRate * track.mScale / 1000000ll; + + if (closestByteOffset <= track.mFirstChunkSize) { + closestSampleIndex = 0; + } else { + closestSampleIndex = + (closestByteOffset - track.mFirstChunkSize) + / track.mAvgChunkSize; + } + } else { + // Each chunk contains a single sample. + closestSampleIndex = timeUs / track.mRate * track.mScale / 1000000ll; + } ssize_t numSamples = track.mSamples.size(); diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index ba076f57bf0e..2581a62eca44 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -508,6 +508,9 @@ status_t AudioPlayer::seekTo(int64_t time_us) { mReachedEOS = false; mSeekTimeUs = time_us; + // Flush resets the number of played frames + mNumFramesPlayed = 0; + if (mAudioSink != NULL) { mAudioSink->flush(); } else { diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 07a46bd20e6c..fa9417a50ebe 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -249,7 +249,7 @@ void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { } void AwesomePlayer::setUID(uid_t uid) { - LOGI("AwesomePlayer running on behalf of uid %d", uid); + LOGV("AwesomePlayer running on behalf of uid %d", uid); mUID = uid; mUIDValid = true; @@ -362,7 +362,7 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { if (!meta->findInt32(kKeyBitRate, &bitrate)) { const char *mime; CHECK(meta->findCString(kKeyMIMEType, &mime)); - LOGW("track of type '%s' does not publish bitrate", mime); + LOGV("track of type '%s' does not publish bitrate", mime); totalBitRate = -1; break; @@ -1192,7 +1192,7 @@ void AwesomePlayer::shutdownVideoDecoder_l() { usleep(1000); } IPCThreadState::self()->flushCommands(); - LOGI("video decoder shutdown completed"); + LOGV("video decoder shutdown completed"); } status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) { @@ -1202,7 +1202,7 @@ status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) { return OK; } - LOGI("attempting to reconfigure to use new surface"); + LOGV("attempting to reconfigure to use new surface"); bool wasPlaying = (mFlags & PLAYING) != 0; diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 6280f51c5db1..ccc8a18aa673 100755 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -625,7 +625,11 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) { CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); - setAACFormat(numChannels, sampleRate, bitRate); + status_t err = setAACFormat(numChannels, sampleRate, bitRate); + if (err != OK) { + CODEC_LOGE("setAACFormat() failed (err = %d)", err); + return err; + } } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME) || !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) { // These are PCM-like formats with a fixed sample rate but @@ -1485,6 +1489,8 @@ void OMXCodec::setComponentRole( "audio_decoder.amrwb", "audio_encoder.amrwb" }, { MEDIA_MIMETYPE_AUDIO_AAC, "audio_decoder.aac", "audio_encoder.aac" }, + { MEDIA_MIMETYPE_AUDIO_VORBIS, + "audio_decoder.vorbis", "audio_encoder.vorbis" }, { MEDIA_MIMETYPE_VIDEO_AVC, "video_decoder.avc", "video_encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, @@ -1635,7 +1641,7 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) { return err; } - CODEC_LOGI("allocating %lu buffers of size %lu on %s port", + CODEC_LOGV("allocating %lu buffers of size %lu on %s port", def.nBufferCountActual, def.nBufferSize, portIndex == kPortIndexInput ? "input" : "output"); @@ -1876,7 +1882,7 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() { return err; } - CODEC_LOGI("allocating %lu buffers from a native window of size %lu on " + CODEC_LOGV("allocating %lu buffers from a native window of size %lu on " "output port", def.nBufferCountActual, def.nBufferSize); // Dequeue buffers and send them to OMX @@ -3356,8 +3362,10 @@ void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) { } } -void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) { - CHECK(numChannels == 1 || numChannels == 2); +status_t OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) { + if (numChannels > 2) + LOGW("Number of channels: (%d) \n", numChannels); + if (mIsEncoder) { //////////////// input port //////////////////// setRawAudioFormat(kPortIndexInput, sampleRate, numChannels); @@ -3408,9 +3416,13 @@ void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bit profile.nAACERtools = OMX_AUDIO_AACERNone; profile.eAACProfile = OMX_AUDIO_AACObjectLC; profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; - CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac, - &profile, sizeof(profile)), (status_t)OK); + err = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, + &profile, sizeof(profile)); + if (err != OK) { + CODEC_LOGE("setParameter('OMX_IndexParamAudioAac') failed (err = %d)", err); + return err; + } } else { OMX_AUDIO_PARAM_AACPROFILETYPE profile; InitOMXParams(&profile); @@ -3426,8 +3438,14 @@ void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bit err = mOMX->setParameter( mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); - CHECK_EQ(err, (status_t)OK); + + if (err != OK) { + CODEC_LOGE("setParameter('OMX_IndexParamAudioAac') failed (err = %d)", err); + return err; + } } + + return OK; } void OMXCodec::setG711Format(int32_t numChannels) { @@ -3654,7 +3672,7 @@ status_t OMXCodec::stop() { mSource->stop(); - CODEC_LOGI("stopped in state %d", mState); + CODEC_LOGV("stopped in state %d", mState); return OK; } @@ -4219,14 +4237,14 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { inputFormat->findInt32(kKeySampleRate, &sampleRate); if ((OMX_U32)numChannels != params.nChannels) { - LOGW("Codec outputs a different number of channels than " + LOGV("Codec outputs a different number of channels than " "the input stream contains (contains %d channels, " "codec outputs %ld channels).", numChannels, params.nChannels); } if (sampleRate != (int32_t)params.nSamplingRate) { - LOGW("Codec outputs at different sampling rate than " + LOGV("Codec outputs at different sampling rate than " "what the input stream contains (contains data at " "%d Hz, codec outputs %lu Hz)", sampleRate, params.nSamplingRate); diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index 306f1f63d49d..2b27ee222d6a 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -764,8 +764,8 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer, // If the loop was exited as a result of stopping the recording, // it is OK if (mStopped) { - LOGV("Read: SurfaceMediaSource is stopped. Returning NO_INIT;"); - return NO_INIT; + LOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM."); + return ERROR_END_OF_STREAM; } // Update the current buffer info diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp index 07aa140929a2..153ee3352c78 100644 --- a/media/libstagefright/avc_utils.cpp +++ b/media/libstagefright/avc_utils.cpp @@ -297,7 +297,7 @@ sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { sp<MetaData> meta = new MetaData; meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); - meta->setData(kKeyAVCC, 0, csd->data(), csd->size()); + meta->setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size()); meta->setInt32(kKeyWidth, width); meta->setInt32(kKeyHeight, height); diff --git a/media/libstagefright/include/AVIExtractor.h b/media/libstagefright/include/AVIExtractor.h index b5753473804b..ff5dcb53ee0c 100644 --- a/media/libstagefright/include/AVIExtractor.h +++ b/media/libstagefright/include/AVIExtractor.h @@ -42,6 +42,7 @@ protected: private: struct AVISource; + struct MP3Splitter; struct SampleInfo { uint32_t mOffset; @@ -70,6 +71,10 @@ private: size_t mThumbnailSampleSize; ssize_t mThumbnailSampleIndex; size_t mMaxSampleSize; + + // If mBytesPerSample > 0: + double mAvgChunkSize; + size_t mFirstChunkSize; }; sp<DataSource> mDataSource; @@ -101,6 +106,7 @@ private: size_t *sampleIndex) const; status_t addMPEG4CodecSpecificData(size_t trackIndex); + status_t addH264CodecSpecificData(size_t trackIndex); static bool IsCorrectChunkType( ssize_t trackIndex, Track::Kind kind, uint32_t chunkType); diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index ffa335646ab7..20a25d7d2664 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -423,74 +423,88 @@ again: MediaBuffer *frame = *mPendingFrames.begin(); mPendingFrames.erase(mPendingFrames.begin()); - size_t size = frame->range_length(); - if (mType != AVC) { *out = frame; return OK; } - if (size < mNALSizeLen) { - frame->release(); - frame = NULL; + // Each input frame contains one or more NAL fragments, each fragment + // is prefixed by mNALSizeLen bytes giving the fragment length, + // followed by a corresponding number of bytes containing the fragment. + // We output all these fragments into a single large buffer separated + // by startcodes (0x00 0x00 0x00 0x01). + + const uint8_t *srcPtr = + (const uint8_t *)frame->data() + frame->range_offset(); + + size_t srcSize = frame->range_length(); + + size_t dstSize = 0; + MediaBuffer *buffer = NULL; + uint8_t *dstPtr = NULL; + + for (int32_t pass = 0; pass < 2; ++pass) { + size_t srcOffset = 0; + size_t dstOffset = 0; + while (srcOffset + mNALSizeLen <= srcSize) { + size_t NALsize; + switch (mNALSizeLen) { + case 1: NALsize = srcPtr[srcOffset]; break; + case 2: NALsize = U16_AT(srcPtr + srcOffset); break; + case 3: NALsize = U24_AT(srcPtr + srcOffset); break; + case 4: NALsize = U32_AT(srcPtr + srcOffset); break; + default: + TRESPASS(); + } - return ERROR_MALFORMED; - } + if (srcOffset + mNALSizeLen + NALsize > srcSize) { + break; + } - // In the case of AVC content, each NAL unit is prefixed by - // mNALSizeLen bytes of length. We want to prefix the data with - // a four-byte 0x00000001 startcode instead of the length prefix. - // mNALSizeLen ranges from 1 through 4 bytes, so add an extra - // 3 bytes of padding to the buffer start. - static const size_t kPadding = 3; + if (pass == 1) { + memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); - MediaBuffer *buffer = new MediaBuffer(size + kPadding); + memcpy(&dstPtr[dstOffset + 4], + &srcPtr[srcOffset + mNALSizeLen], + NALsize); + } - int64_t timeUs; - CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); - int32_t isSync; - CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); + dstOffset += 4; // 0x00 00 00 01 + dstOffset += NALsize; - buffer->meta_data()->setInt64(kKeyTime, timeUs); - buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); + srcOffset += mNALSizeLen + NALsize; + } - memcpy((uint8_t *)buffer->data() + kPadding, - (const uint8_t *)frame->data() + frame->range_offset(), - size); + if (srcOffset < srcSize) { + // There were trailing bytes or not enough data to complete + // a fragment. - buffer->set_range(kPadding, size); + frame->release(); + frame = NULL; - frame->release(); - frame = NULL; + return ERROR_MALFORMED; + } - uint8_t *data = (uint8_t *)buffer->data(); + if (pass == 0) { + dstSize = dstOffset; - size_t NALsize; - switch (mNALSizeLen) { - case 1: NALsize = data[kPadding]; break; - case 2: NALsize = U16_AT(&data[kPadding]); break; - case 3: NALsize = U24_AT(&data[kPadding]); break; - case 4: NALsize = U32_AT(&data[kPadding]); break; - default: - TRESPASS(); - } + buffer = new MediaBuffer(dstSize); - if (size < NALsize + mNALSizeLen) { - buffer->release(); - buffer = NULL; + int64_t timeUs; + CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); + int32_t isSync; + CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); - return ERROR_MALFORMED; - } + buffer->meta_data()->setInt64(kKeyTime, timeUs); + buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); - if (size > NALsize + mNALSizeLen) { - LOGW("discarding %d bytes of data.", size - NALsize - mNALSizeLen); + dstPtr = (uint8_t *)buffer->data(); + } } - // actual data starts at &data[kPadding + mNALSizeLen] - - memcpy(&data[mNALSizeLen - 1], "\x00\x00\x00\x01", 4); - buffer->set_range(mNALSizeLen - 1, NALsize + 4); + frame->release(); + frame = NULL; *out = buffer; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java index f3cf0f71c6bb..3fb2da080954 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java @@ -17,27 +17,26 @@ package com.android.mediaframeworktest; import com.android.mediaframeworktest.functional.CameraTest; -import com.android.mediaframeworktest.functional.MediaAudioTrackTest; import com.android.mediaframeworktest.functional.MediaMetadataTest; import com.android.mediaframeworktest.functional.MediaMimeTest; -import com.android.mediaframeworktest.functional.MediaPlayerApiTest; -import com.android.mediaframeworktest.functional.MediaRecorderTest; -import com.android.mediaframeworktest.functional.SimTonesTest; import com.android.mediaframeworktest.functional.MediaPlayerInvokeTest; -import com.android.mediaframeworktest.functional.MediaAudioManagerTest; -import com.android.mediaframeworktest.functional.MediaAudioEffectTest; -import com.android.mediaframeworktest.functional.MediaBassBoostTest; -import com.android.mediaframeworktest.functional.MediaEnvReverbTest; -import com.android.mediaframeworktest.functional.MediaEqualizerTest; -import com.android.mediaframeworktest.functional.MediaPresetReverbTest; -import com.android.mediaframeworktest.functional.MediaVirtualizerTest; -import com.android.mediaframeworktest.functional.MediaVisualizerTest; -/*import for VideoEditor Test cases*/ -import com.android.mediaframeworktest.functional.MediaItemThumbnailTest; -import com.android.mediaframeworktest.functional.MediaPropertiesTest; -import com.android.mediaframeworktest.functional.VideoEditorAPITest; -import com.android.mediaframeworktest.functional.VideoEditorExportTest; -import com.android.mediaframeworktest.functional.VideoEditorPreviewTest; +import com.android.mediaframeworktest.functional.mediaplayback.MediaPlayerApiTest; +import com.android.mediaframeworktest.functional.mediarecorder.MediaRecorderTest; +import com.android.mediaframeworktest.functional.audio.SimTonesTest; +import com.android.mediaframeworktest.functional.audio.MediaAudioTrackTest; +import com.android.mediaframeworktest.functional.audio.MediaAudioManagerTest; +import com.android.mediaframeworktest.functional.audio.MediaAudioEffectTest; +import com.android.mediaframeworktest.functional.audio.MediaBassBoostTest; +import com.android.mediaframeworktest.functional.audio.MediaEnvReverbTest; +import com.android.mediaframeworktest.functional.audio.MediaEqualizerTest; +import com.android.mediaframeworktest.functional.audio.MediaPresetReverbTest; +import com.android.mediaframeworktest.functional.audio.MediaVirtualizerTest; +import com.android.mediaframeworktest.functional.audio.MediaVisualizerTest; +import com.android.mediaframeworktest.functional.videoeditor.MediaItemThumbnailTest; +import com.android.mediaframeworktest.functional.videoeditor.MediaPropertiesTest; +import com.android.mediaframeworktest.functional.videoeditor.VideoEditorAPITest; +import com.android.mediaframeworktest.functional.videoeditor.VideoEditorExportTest; +import com.android.mediaframeworktest.functional.videoeditor.VideoEditorPreviewTest; import junit.framework.TestSuite; import android.test.InstrumentationTestRunner; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioEffectTest.java index 1511cd795229..ab78714cb56e 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioEffectTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; @@ -1529,4 +1529,3 @@ public class MediaAudioEffectTest extends ActivityInstrumentationTestCase2<Media } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioManagerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java index 644444ae90df..c9087d14665f 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioManagerTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioManagerTest.java @@ -14,7 +14,7 @@ * the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import android.content.Context; @@ -67,4 +67,4 @@ public class MediaAudioManagerTest extends ActivityInstrumentationTestCase2<Medi assertTrue("SetRingtoneMode : " + ringtoneMode[i], result); } } - }
\ No newline at end of file + } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioTrackTest.java index cea3a5a797a5..e884aba7bcf7 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioTrackTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; @@ -1250,4 +1250,3 @@ public class MediaAudioTrackTest extends ActivityInstrumentationTestCase2<MediaF } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaBassBoostTest.java index aa5c4d7c8653..e3aa8cf86cf9 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaBassBoostTest.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; +import com.android.mediaframeworktest.functional.EnergyProbe; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.media.audiofx.AudioEffect; @@ -46,6 +47,10 @@ public class MediaBassBoostTest extends ActivityInstrumentationTestCase2<MediaFr private final static int MIN_ENERGY_RATIO_2 = 3; private final static short TEST_STRENGTH = 500; private final static int TEST_VOLUME = 4; + // Implementor UUID for volume controller effect defined in + // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp + private final static UUID VOLUME_EFFECT_UUID = + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"); private BassBoost mBassBoost = null; private int mSession = -1; @@ -201,14 +206,15 @@ public class MediaBassBoostTest extends ActivityInstrumentationTestCase2<MediaFr // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); mp.setDataSource(MediaNames.SINE_200_1000); + mp.setLooping(true); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); getBassBoost(mp.getAudioSessionId()); mp.prepare(); @@ -219,7 +225,7 @@ public class MediaBassBoostTest extends ActivityInstrumentationTestCase2<MediaFr int refEnergy1000 = probe.capture(1000); mBassBoost.setStrength((short)1000); mBassBoost.setEnabled(true); - Thread.sleep(500); + Thread.sleep(4000); // measure energy around 1kHz with band level at min int energy200 = probe.capture(200); int energy1000 = probe.capture(1000); @@ -286,4 +292,3 @@ public class MediaBassBoostTest extends ActivityInstrumentationTestCase2<MediaFr } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaEnvReverbTest.java index ba202a730a72..3c8d05a027e7 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaEnvReverbTest.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; +import com.android.mediaframeworktest.functional.EnergyProbe; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.media.audiofx.AudioEffect; @@ -49,6 +50,14 @@ public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFr private final static float DELAY_TOLERANCE = 1.05f; // allow +/- 5% tolerance between set and get ratios private final static float RATIO_TOLERANCE = 1.05f; + // Implementor UUID for volume controller effect defined in + // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp + private final static UUID VOLUME_EFFECT_UUID = + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"); + // Implementor UUID for environmental reverb effect defined in + // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp + private final static UUID ENV_REVERB_EFFECT_UUID = + UUID.fromString("c7a511a0-a3bb-11df-860e-0002a5d5c51b"); private EnvironmentalReverb mReverb = null; private int mSession = -1; @@ -354,10 +363,10 @@ public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFr // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); @@ -424,10 +433,10 @@ public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFr // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); @@ -438,7 +447,7 @@ public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFr // auxiliary reverb will be chosen by the effect framework as we are on session 0 rvb = new AudioEffect( AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("c7a511a0-a3bb-11df-860e-0002a5d5c51b"), + ENV_REVERB_EFFECT_UUID, 0, 0); @@ -520,4 +529,3 @@ public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFr } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaEqualizerTest.java index 9146fb813b54..ee91bbb34d76 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaEqualizerTest.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; +import com.android.mediaframeworktest.functional.EnergyProbe; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.media.audiofx.AudioEffect; @@ -49,6 +50,11 @@ public class MediaEqualizerTest extends ActivityInstrumentationTestCase2<MediaFr private final static int TEST_FREQUENCY_MILLIHERTZ = 1000000; private final static int MIN_NUMBER_OF_PRESETS = 4; private final static int TEST_VOLUME = 4; + // Implementor UUID for volume controller effect defined in + // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp + private final static UUID VOLUME_EFFECT_UUID = + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"); + private Equalizer mEqualizer = null; private int mSession = -1; @@ -267,10 +273,10 @@ public class MediaEqualizerTest extends ActivityInstrumentationTestCase2<MediaFr // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); @@ -349,4 +355,3 @@ public class MediaEqualizerTest extends ActivityInstrumentationTestCase2<MediaFr } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaPresetReverbTest.java index 242e6bb50a3d..757bbc5fb394 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaPresetReverbTest.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; +import com.android.mediaframeworktest.functional.EnergyProbe; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.media.audiofx.AudioEffect; @@ -43,6 +44,14 @@ import java.util.UUID; */ public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { private String TAG = "MediaPresetReverbTest"; + // Implementor UUID for volume controller effect defined in + // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp + private final static UUID VOLUME_EFFECT_UUID = + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"); + // Implementor UUID for preset reverb effect defined in + // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp + private final static UUID PRESET_REVERB_EFFECT_UUID = + UUID.fromString("172cdf00-a3bc-11df-a72f-0002a5d5c51b"); private PresetReverb mReverb = null; private int mSession = -1; @@ -199,10 +208,10 @@ public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<Medi // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); @@ -267,24 +276,21 @@ public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<Medi // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); mp.setDataSource(MediaNames.SINE_200_1000); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); - getReverb(mp.getAudioSessionId()); - mReverb.setPreset((short)PresetReverb.PRESET_PLATE); - mReverb.setEnabled(true); // create reverb with UUID instead of PresetReverb constructor otherwise an auxiliary // reverb will be chosen by the effect framework as we are on session 0 rvb = new AudioEffect( AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("172cdf00-a3bc-11df-a72f-0002a5d5c51b"), + PRESET_REVERB_EFFECT_UUID, 0, 0); @@ -317,7 +323,6 @@ public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<Medi loge(msg, "sleep() interrupted"); } finally { - releaseReverb(); if (mp != null) { mp.release(); } @@ -365,4 +370,3 @@ public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<Medi } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaVirtualizerTest.java index 7a35429745b0..b74e52591cb7 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaVirtualizerTest.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; +import com.android.mediaframeworktest.functional.EnergyProbe; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.media.audiofx.AudioEffect; @@ -43,9 +44,13 @@ import java.util.UUID; */ public class MediaVirtualizerTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { private String TAG = "MediaVirtualizerTest"; - private final static int MIN_ENERGY_RATIO_2 = 3; + private final static int MIN_ENERGY_RATIO_2 = 2; private final static short TEST_STRENGTH = 500; private final static int TEST_VOLUME = 4; + // Implementor UUID for volume controller effect defined in + // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp + private final static UUID VOLUME_EFFECT_UUID = + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"); private Virtualizer mVirtualizer = null; private int mSession = -1; @@ -202,14 +207,15 @@ public class MediaVirtualizerTest extends ActivityInstrumentationTestCase2<Media // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); mp.setDataSource(MediaNames.SINE_200_1000); + mp.setLooping(true); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); getVirtualizer(mp.getAudioSessionId()); mp.prepare(); @@ -220,7 +226,7 @@ public class MediaVirtualizerTest extends ActivityInstrumentationTestCase2<Media int refEnergy1000 = probe.capture(1000); mVirtualizer.setStrength((short)1000); mVirtualizer.setEnabled(true); - Thread.sleep(500); + Thread.sleep(4000); // measure energy around 1kHz with band level at min int energy200 = probe.capture(200); int energy1000 = probe.capture(1000); @@ -230,7 +236,7 @@ public class MediaVirtualizerTest extends ActivityInstrumentationTestCase2<Media // audio file but is not the primary effect of the virtualizer. A better way would // be to have a stereo PCM capture and check that a strongly paned input is centered // when output. However, we cannot capture stereo with the visualizer. - assertTrue(msg + ": virtiualizer has no effect", + assertTrue(msg + ": virtualizer has no effect", ((float)energy200/(float)energy1000) > (MIN_ENERGY_RATIO_2 * ((float)refEnergy200/(float)refEnergy1000))); result = true; @@ -291,4 +297,3 @@ public class MediaVirtualizerTest extends ActivityInstrumentationTestCase2<Media } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaVisualizerTest.java index 542ca8d6f4dc..e0cf51d0a4d7 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaVisualizerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; @@ -47,6 +47,10 @@ public class MediaVisualizerTest extends ActivityInstrumentationTestCase2<MediaF private final static int MAX_SAMPLING_RATE = 48000000; private final static int MIN_CAPTURE_SIZE_MAX = 1024; private final static int MAX_CAPTURE_SIZE_MIN = 128; + // Implementor UUID for volume controller effect defined in + // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp + private final static UUID VOLUME_EFFECT_UUID = + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"); private Visualizer mVisualizer = null; private int mSession = -1; @@ -205,10 +209,10 @@ public class MediaVisualizerTest extends ActivityInstrumentationTestCase2<MediaF // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); @@ -281,10 +285,10 @@ public class MediaVisualizerTest extends ActivityInstrumentationTestCase2<MediaF // creating a volume controller on output mix ensures that ro.audio.silent mutes // audio after the effects and not before vc = new AudioEffect( - AudioEffect.EFFECT_TYPE_NULL, - UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), - 0, - 0); + AudioEffect.EFFECT_TYPE_NULL, + VOLUME_EFFECT_UUID, + 0, + 0); vc.setEnabled(true); mp = new MediaPlayer(); @@ -502,4 +506,3 @@ public class MediaVisualizerTest extends ActivityInstrumentationTestCase2<MediaF } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/SimTonesTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/SimTonesTest.java index 241f8d6b7327..aaf992cc07a7 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/SimTonesTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/SimTonesTest.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.audio; // import android.content.Resources; import com.android.mediaframeworktest.MediaFrameworkTest; +import com.android.mediaframeworktest.functional.TonesAutoTest; import android.content.Context; import android.test.ActivityInstrumentationTestCase; @@ -70,4 +71,3 @@ public class SimTonesTest extends ActivityInstrumentationTestCase<MediaFramework assertTrue("Stress Tones", result); } } - diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediaplayback/MediaPlayerApiTest.java index 57d5368eba0a..c501d3f189f2 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediaplayback/MediaPlayerApiTest.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.mediaplayback; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; import com.android.mediaframeworktest.MediaProfileReader; +import com.android.mediaframeworktest.functional.CodecTest; import android.content.Context; import android.test.ActivityInstrumentationTestCase; @@ -31,16 +32,15 @@ import java.io.File; /** * Junit / Instrumentation test case for the media player api - - */ -public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> { + */ +public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> { private boolean duratoinWithinTolerence = false; private String TAG = "MediaPlayerApiTest"; private boolean isWMAEnable = false; private boolean isWMVEnable = false; - + Context mContext; - + public MediaPlayerApiTest() { super("com.android.mediaframeworktest", MediaFrameworkTest.class); isWMAEnable = MediaProfileReader.getWMAEnable(); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java index 796b52cb77f0..b5c8c8c486f0 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.mediarecorder; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaItemThumbnailTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaItemThumbnailTest.java index d5b67aa6f017..80a3bcd370a1 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaItemThumbnailTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaItemThumbnailTest.java @@ -15,7 +15,7 @@ */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.videoeditor; import java.io.File; import java.io.IOException; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaPropertiesTest.java index 0ad6760d1ee8..e2f68637ba42 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaPropertiesTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.videoeditor; import java.io.File; import java.io.IOException; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorAPITest.java index 2a02b58f0bfa..b32d865d083a 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorAPITest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.videoeditor; import java.io.File; import java.util.List; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorExportTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorExportTest.java index e1b337df9c8a..57a1c75e86f4 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorExportTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorExportTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.videoeditor; import java.io.File; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java index 9a7f4f2ee5c2..e848f5f5b105 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.mediaframeworktest.functional; +package com.android.mediaframeworktest.functional.videoeditor; import java.io.File; import java.io.IOException; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java index 873759540684..91100aef07bf 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java @@ -20,6 +20,7 @@ import android.media.MediaRecorder; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; /** * Unit test class to test the set of valid and invalid states that @@ -27,6 +28,8 @@ import android.test.suitebuilder.annotation.Suppress; */ public class MediaRecorderStopStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest { private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate(); + private static final String TAG = "MediaRecorderStopStateUnitTest"; + private static final int SLEEP_TIME_BEFORE_STOP = 1000; /** * 1. It is valid to call stop() in the following states: @@ -51,6 +54,15 @@ public class MediaRecorderStopStateUnitTest extends AndroidTestCase implements M } public void invokeMethodUnderTest(MediaRecorder recorder) { + // Wait for some time before stopping the media recorder. + // This will fix the assertion caused by stopping it immediatedly + // after it is started + try { + Thread.sleep(SLEEP_TIME_BEFORE_STOP); + } catch(Exception e) { + Log.v(TAG, "sleep was interrupted and terminated prematurely"); + } + recorder.stop(); } diff --git a/opengl/java/android/opengl/Matrix.java b/opengl/java/android/opengl/Matrix.java index 6d80bc60c94a..7c72ae470c52 100644 --- a/opengl/java/android/opengl/Matrix.java +++ b/opengl/java/android/opengl/Matrix.java @@ -39,6 +39,10 @@ package android.opengl; * */ public class Matrix { + + /** Temporary memory for operations that need temporary matrix data. */ + private final static float[] sTemp = new float[32]; + /** * Multiply two 4x4 matrices together and store the result in a third 4x4 * matrix. In matrix notation: result = lhs x rhs. Due to the way @@ -125,95 +129,120 @@ public class Matrix { int mOffset) { // Invert a 4 x 4 matrix using Cramer's Rule - // array of transpose source matrix - float[] src = new float[16]; - // transpose matrix - transposeM(src, 0, m, mOffset); - - // temp array for pairs - float[] tmp = new float[12]; + final float src0 = m[mOffset + 0]; + final float src4 = m[mOffset + 1]; + final float src8 = m[mOffset + 2]; + final float src12 = m[mOffset + 3]; + + final float src1 = m[mOffset + 4]; + final float src5 = m[mOffset + 5]; + final float src9 = m[mOffset + 6]; + final float src13 = m[mOffset + 7]; + + final float src2 = m[mOffset + 8]; + final float src6 = m[mOffset + 9]; + final float src10 = m[mOffset + 10]; + final float src14 = m[mOffset + 11]; + + final float src3 = m[mOffset + 12]; + final float src7 = m[mOffset + 13]; + final float src11 = m[mOffset + 14]; + final float src15 = m[mOffset + 15]; // calculate pairs for first 8 elements (cofactors) - tmp[0] = src[10] * src[15]; - tmp[1] = src[11] * src[14]; - tmp[2] = src[9] * src[15]; - tmp[3] = src[11] * src[13]; - tmp[4] = src[9] * src[14]; - tmp[5] = src[10] * src[13]; - tmp[6] = src[8] * src[15]; - tmp[7] = src[11] * src[12]; - tmp[8] = src[8] * src[14]; - tmp[9] = src[10] * src[12]; - tmp[10] = src[8] * src[13]; - tmp[11] = src[9] * src[12]; - - // Holds the destination matrix while we're building it up. - float[] dst = new float[16]; + final float atmp0 = src10 * src15; + final float atmp1 = src11 * src14; + final float atmp2 = src9 * src15; + final float atmp3 = src11 * src13; + final float atmp4 = src9 * src14; + final float atmp5 = src10 * src13; + final float atmp6 = src8 * src15; + final float atmp7 = src11 * src12; + final float atmp8 = src8 * src14; + final float atmp9 = src10 * src12; + final float atmp10 = src8 * src13; + final float atmp11 = src9 * src12; // calculate first 8 elements (cofactors) - dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]; - dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]; - dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]; - dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7]; - dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7]; - dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7]; - dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6]; - dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6]; - dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3]; - dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3]; - dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3]; - dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3]; - dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3]; - dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]; - dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]; - dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]; + final float dst0 = (atmp0 * src5 + atmp3 * src6 + atmp4 * src7) + - (atmp1 * src5 + atmp2 * src6 + atmp5 * src7); + final float dst1 = (atmp1 * src4 + atmp6 * src6 + atmp9 * src7) + - (atmp0 * src4 + atmp7 * src6 + atmp8 * src7); + final float dst2 = (atmp2 * src4 + atmp7 * src5 + atmp10 * src7) + - (atmp3 * src4 + atmp6 * src5 + atmp11 * src7); + final float dst3 = (atmp5 * src4 + atmp8 * src5 + atmp11 * src6) + - (atmp4 * src4 + atmp9 * src5 + atmp10 * src6); + final float dst4 = (atmp1 * src1 + atmp2 * src2 + atmp5 * src3) + - (atmp0 * src1 + atmp3 * src2 + atmp4 * src3); + final float dst5 = (atmp0 * src0 + atmp7 * src2 + atmp8 * src3) + - (atmp1 * src0 + atmp6 * src2 + atmp9 * src3); + final float dst6 = (atmp3 * src0 + atmp6 * src1 + atmp11 * src3) + - (atmp2 * src0 + atmp7 * src1 + atmp10 * src3); + final float dst7 = (atmp4 * src0 + atmp9 * src1 + atmp10 * src2) + - (atmp5 * src0 + atmp8 * src1 + atmp11 * src2); // calculate pairs for second 8 elements (cofactors) - tmp[0] = src[2] * src[7]; - tmp[1] = src[3] * src[6]; - tmp[2] = src[1] * src[7]; - tmp[3] = src[3] * src[5]; - tmp[4] = src[1] * src[6]; - tmp[5] = src[2] * src[5]; - tmp[6] = src[0] * src[7]; - tmp[7] = src[3] * src[4]; - tmp[8] = src[0] * src[6]; - tmp[9] = src[2] * src[4]; - tmp[10] = src[0] * src[5]; - tmp[11] = src[1] * src[4]; + final float btmp0 = src2 * src7; + final float btmp1 = src3 * src6; + final float btmp2 = src1 * src7; + final float btmp3 = src3 * src5; + final float btmp4 = src1 * src6; + final float btmp5 = src2 * src5; + final float btmp6 = src0 * src7; + final float btmp7 = src3 * src4; + final float btmp8 = src0 * src6; + final float btmp9 = src2 * src4; + final float btmp10 = src0 * src5; + final float btmp11 = src1 * src4; // calculate second 8 elements (cofactors) - dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; - dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; - dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; - dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15]; - dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15]; - dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15]; - dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14]; - dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14]; - dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9]; - dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10]; - dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10]; - dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8]; - dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8]; - dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]; - dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]; - dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]; + final float dst8 = (btmp0 * src13 + btmp3 * src14 + btmp4 * src15) + - (btmp1 * src13 + btmp2 * src14 + btmp5 * src15); + final float dst9 = (btmp1 * src12 + btmp6 * src14 + btmp9 * src15) + - (btmp0 * src12 + btmp7 * src14 + btmp8 * src15); + final float dst10 = (btmp2 * src12 + btmp7 * src13 + btmp10 * src15) + - (btmp3 * src12 + btmp6 * src13 + btmp11 * src15); + final float dst11 = (btmp5 * src12 + btmp8 * src13 + btmp11 * src14) + - (btmp4 * src12 + btmp9 * src13 + btmp10 * src14); + final float dst12 = (btmp2 * src10 + btmp5 * src11 + btmp1 * src9 ) + - (btmp4 * src11 + btmp0 * src9 + btmp3 * src10); + final float dst13 = (btmp8 * src11 + btmp0 * src8 + btmp7 * src10) + - (btmp6 * src10 + btmp9 * src11 + btmp1 * src8 ); + final float dst14 = (btmp6 * src9 + btmp11 * src11 + btmp3 * src8 ) + - (btmp10 * src11 + btmp2 * src8 + btmp7 * src9 ); + final float dst15 = (btmp10 * src10 + btmp4 * src8 + btmp9 * src9 ) + - (btmp8 * src9 + btmp11 * src10 + btmp5 * src8 ); // calculate determinant - float det = - src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] - * dst[3]; + final float det = + src0 * dst0 + src1 * dst1 + src2 * dst2 + src3 * dst3; if (det == 0.0f) { - + return false; } // calculate matrix inverse - det = 1 / det; - for (int j = 0; j < 16; j++) - mInv[j + mInvOffset] = dst[j] * det; + final float invdet = 1.0f / det; + mInv[ mInvOffset] = dst0 * invdet; + mInv[ 1 + mInvOffset] = dst1 * invdet; + mInv[ 2 + mInvOffset] = dst2 * invdet; + mInv[ 3 + mInvOffset] = dst3 * invdet; + + mInv[ 4 + mInvOffset] = dst4 * invdet; + mInv[ 5 + mInvOffset] = dst5 * invdet; + mInv[ 6 + mInvOffset] = dst6 * invdet; + mInv[ 7 + mInvOffset] = dst7 * invdet; + + mInv[ 8 + mInvOffset] = dst8 * invdet; + mInv[ 9 + mInvOffset] = dst9 * invdet; + mInv[10 + mInvOffset] = dst10 * invdet; + mInv[11 + mInvOffset] = dst11 * invdet; + + mInv[12 + mInvOffset] = dst12 * invdet; + mInv[13 + mInvOffset] = dst13 * invdet; + mInv[14 + mInvOffset] = dst14 * invdet; + mInv[15 + mInvOffset] = dst15 * invdet; return true; } @@ -488,9 +517,10 @@ public class Matrix { public static void rotateM(float[] rm, int rmOffset, float[] m, int mOffset, float a, float x, float y, float z) { - float[] r = new float[16]; - setRotateM(r, 0, a, x, y, z); - multiplyMM(rm, rmOffset, m, mOffset, r, 0); + synchronized(sTemp) { + setRotateM(sTemp, 0, a, x, y, z); + multiplyMM(rm, rmOffset, m, mOffset, sTemp, 0); + } } /** @@ -505,10 +535,11 @@ public class Matrix { */ public static void rotateM(float[] m, int mOffset, float a, float x, float y, float z) { - float[] temp = new float[32]; - setRotateM(temp, 0, a, x, y, z); - multiplyMM(temp, 16, m, mOffset, temp, 0); - System.arraycopy(temp, 16, m, mOffset, 16); + synchronized(sTemp) { + setRotateM(sTemp, 0, a, x, y, z); + multiplyMM(sTemp, 16, m, mOffset, sTemp, 0); + System.arraycopy(sTemp, 16, m, mOffset, 16); + } } /** diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 6e5f8567eea9..113f0f721d38 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -156,6 +156,7 @@ public class DefaultContainerService extends IntentService { } ret.packageName = pkg.packageName; ret.installLocation = pkg.installLocation; + ret.verifiers = pkg.verifiers; ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation, archiveFilePath, flags, threshold); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index 4f39e6980f5b..b851ab7ec81c 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -16,6 +16,21 @@ package com.android.providers.settings; +import android.app.backup.BackupAgentHelper; +import android.app.backup.BackupDataInput; +import android.app.backup.BackupDataOutput; +import android.app.backup.FullBackupDataOutput; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.net.wifi.WifiManager; +import android.os.FileUtils; +import android.os.ParcelFileDescriptor; +import android.os.Process; +import android.provider.Settings; +import android.util.Log; + import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -27,28 +42,13 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; -import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import java.util.zip.CRC32; -import android.app.backup.BackupDataInput; -import android.app.backup.BackupDataOutput; -import android.app.backup.BackupAgentHelper; -import android.app.backup.FullBackupDataOutput; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.net.wifi.WifiManager; -import android.os.FileUtils; -import android.os.ParcelFileDescriptor; -import android.os.Process; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.Log; - /** * Performs backup and restore of the System and Secure settings. * List of settings that are backed up are stored in the Settings.java file @@ -79,8 +79,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { // Versioning of the 'full backup' format private static final int FULL_BACKUP_VERSION = 1; - private static String[] sortedSystemKeys = null; - private static String[] sortedSecureKeys = null; + private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE; private static final byte[] EMPTY_DATA = new byte[0]; @@ -112,6 +111,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { private WifiManager mWfm; private static String mWifiConfigFile; + @Override public void onCreate() { if (DEBUG_BACKUP) Log.d(TAG, "onCreate() invoked"); @@ -348,26 +348,17 @@ public class SettingsBackupAgent extends BackupAgentHelper { } private byte[] getSystemSettings() { - Cursor sortedCursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, - null, null, Settings.NameValueTable.NAME); - // Copy and sort the array - if (sortedSystemKeys == null) { - sortedSystemKeys = copyAndSort(Settings.System.SETTINGS_TO_BACKUP); - } - byte[] result = extractRelevantValues(sortedCursor, sortedSystemKeys); - sortedCursor.close(); + Cursor cursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null, + null, null); + byte[] result = extractRelevantValues(cursor, Settings.System.SETTINGS_TO_BACKUP); + cursor.close(); return result; } private byte[] getSecureSettings() { - Cursor sortedCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION, - null, null, Settings.NameValueTable.NAME); - // Copy and sort the array - if (sortedSecureKeys == null) { - sortedSecureKeys = copyAndSort(Settings.Secure.SETTINGS_TO_BACKUP); - } - byte[] result = extractRelevantValues(sortedCursor, sortedSecureKeys); - sortedCursor.close(); + Cursor cursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION, null, + null, null); + byte[] result = extractRelevantValues(cursor, Settings.Secure.SETTINGS_TO_BACKUP); return result; } @@ -383,119 +374,132 @@ public class SettingsBackupAgent extends BackupAgentHelper { } private void restoreSettings(byte[] settings, int bytes, Uri contentUri) { - if (DEBUG) Log.i(TAG, "restoreSettings: " + contentUri); + if (DEBUG) { + Log.i(TAG, "restoreSettings: " + contentUri); + } + + // Figure out the white list. String[] whitelist = null; if (contentUri.equals(Settings.Secure.CONTENT_URI)) { whitelist = Settings.Secure.SETTINGS_TO_BACKUP; } else if (contentUri.equals(Settings.System.CONTENT_URI)) { whitelist = Settings.System.SETTINGS_TO_BACKUP; + } else { + throw new IllegalArgumentException("Unknown URI: " + contentUri); } - ContentValues cv = new ContentValues(2); + // Restore only the white list data. int pos = 0; - while (pos < bytes) { - int length = readInt(settings, pos); - pos += 4; - String settingName = length > 0? new String(settings, pos, length) : null; - pos += length; - length = readInt(settings, pos); - pos += 4; - String settingValue = length > 0? new String(settings, pos, length) : null; - pos += length; - if (!TextUtils.isEmpty(settingName) && !TextUtils.isEmpty(settingValue)) { - //Log.i(TAG, "Restore " + settingName + " = " + settingValue); - - // Only restore settings in our list of known-acceptable data - if (invalidSavedSetting(whitelist, settingName)) { - continue; + Map<String, String> cachedEntries = new HashMap<String, String>(); + ContentValues contentValues = new ContentValues(2); + SettingsHelper settingsHelper = mSettingsHelper; + + final int whiteListSize = whitelist.length; + for (int i = 0; i < whiteListSize; i++) { + String key = whitelist[i]; + String value = cachedEntries.remove(key); + + // If the value not cached, let us look it up. + if (value == null) { + while (pos < bytes) { + int length = readInt(settings, pos); + pos += INTEGER_BYTE_COUNT; + String dataKey = length > 0 ? new String(settings, pos, length) : null; + pos += length; + length = readInt(settings, pos); + pos += INTEGER_BYTE_COUNT; + String dataValue = length > 0 ? new String(settings, pos, length) : null; + pos += length; + if (key.equals(dataKey)) { + value = dataValue; + break; + } + cachedEntries.put(dataKey, dataValue); } + } - if (mSettingsHelper.restoreValue(settingName, settingValue)) { - cv.clear(); - cv.put(Settings.NameValueTable.NAME, settingName); - cv.put(Settings.NameValueTable.VALUE, settingValue); - getContentResolver().insert(contentUri, cv); - } + if (value == null) { + continue; } - } - } - // Returns 'true' if the given setting is one that we refuse to restore - private boolean invalidSavedSetting(String[] knownNames, String candidate) { - // no filter? allow everything - if (knownNames == null) { - return false; - } + if (settingsHelper.restoreValue(key, value)) { + contentValues.clear(); + contentValues.put(Settings.NameValueTable.NAME, key); + contentValues.put(Settings.NameValueTable.VALUE, value); + getContentResolver().insert(contentUri, contentValues); + } - // whitelisted setting? allow it - for (String name : knownNames) { - if (name.equals(candidate)) { - return false; + if (DEBUG) { + Log.d(TAG, "Restored setting: " + key + "=" + value); } } - - // refuse everything else - if (DEBUG) Log.v(TAG, "Ignoring restore datum: " + candidate); - return true; - } - - private String[] copyAndSort(String[] keys) { - String[] sortedKeys = new String[keys.length]; - System.arraycopy(keys, 0, sortedKeys, 0, keys.length); - Arrays.sort(sortedKeys); - return sortedKeys; } /** - * Given a cursor sorted by key name and a set of keys sorted by name, - * extract the required keys and values and write them to a byte array. - * @param sortedCursor - * @param sortedKeys - * @return + * Given a cursor and a set of keys, extract the required keys and + * values and write them to a byte array. + * + * @param cursor A cursor with settings data. + * @param settings The settings to extract. + * @return The byte array of extracted values. */ - byte[] extractRelevantValues(Cursor sortedCursor, String[] sortedKeys) { - byte[][] values = new byte[sortedKeys.length * 2][]; // keys and values - if (!sortedCursor.moveToFirst()) { + private byte[] extractRelevantValues(Cursor cursor, String[] settings) { + final int settingsCount = settings.length; + byte[][] values = new byte[settingsCount * 2][]; // keys and values + if (!cursor.moveToFirst()) { Log.e(TAG, "Couldn't read from the cursor"); return new byte[0]; } - int keyIndex = 0; + + // Obtain the relevant data in a temporary array. int totalSize = 0; - while (!sortedCursor.isAfterLast()) { - String name = sortedCursor.getString(COLUMN_NAME); - while (sortedKeys[keyIndex].compareTo(name.toString()) < 0) { - keyIndex++; - if (keyIndex == sortedKeys.length) break; - } - if (keyIndex < sortedKeys.length && name.equals(sortedKeys[keyIndex])) { - String value = sortedCursor.getString(COLUMN_VALUE); - byte[] nameBytes = name.toString().getBytes(); - totalSize += 4 + nameBytes.length; - values[keyIndex * 2] = nameBytes; - byte[] valueBytes; - if (TextUtils.isEmpty(value)) { - valueBytes = null; - totalSize += 4; - } else { - valueBytes = value.toString().getBytes(); - totalSize += 4 + valueBytes.length; - //Log.i(TAG, "Backing up " + name + " = " + value); + int backedUpSettingIndex = 0; + Map<String, String> cachedEntries = new HashMap<String, String>(); + for (int i = 0; i < settingsCount; i++) { + String key = settings[i]; + String value = cachedEntries.remove(key); + + // If the value not cached, let us look it up. + if (value == null) { + while (!cursor.isAfterLast()) { + String cursorKey = cursor.getString(COLUMN_NAME); + String cursorValue = cursor.getString(COLUMN_VALUE); + cursor.moveToNext(); + if (key.equals(cursorKey)) { + value = cursorValue; + break; + } + cachedEntries.put(cursorKey, cursorValue); } - values[keyIndex * 2 + 1] = valueBytes; - keyIndex++; } - if (keyIndex == sortedKeys.length || !sortedCursor.moveToNext()) { - break; + + if (value == null) { + continue; + } + + // Write the key and value in the intermediary array. + byte[] keyBytes = key.getBytes(); + totalSize += INTEGER_BYTE_COUNT + keyBytes.length; + values[backedUpSettingIndex * 2] = keyBytes; + + byte[] valueBytes = value.getBytes(); + totalSize += INTEGER_BYTE_COUNT + valueBytes.length; + values[backedUpSettingIndex * 2 + 1] = valueBytes; + + backedUpSettingIndex++; + + if (DEBUG) { + Log.d(TAG, "Backed up setting: " + key + "=" + value); } } + // Aggregate the result. byte[] result = new byte[totalSize]; int pos = 0; - for (int i = 0; i < sortedKeys.length * 2; i++) { - if (values[i] != null) { - pos = writeInt(result, pos, values[i].length); - pos = writeBytes(result, pos, values[i]); - } + final int keyValuePairCount = backedUpSettingIndex * 2; + for (int i = 0; i < keyValuePairCount; i++) { + pos = writeInt(result, pos, values[i].length); + pos = writeBytes(result, pos, values[i]); } return result; } @@ -647,14 +651,14 @@ public class SettingsBackupAgent extends BackupAgentHelper { * @param out byte array * @param pos current pos in array * @param value integer to write - * @return the index after adding the size of an int (4) + * @return the index after adding the size of an int (4) in bytes. */ private int writeInt(byte[] out, int pos, int value) { out[pos + 0] = (byte) ((value >> 24) & 0xFF); out[pos + 1] = (byte) ((value >> 16) & 0xFF); out[pos + 2] = (byte) ((value >> 8) & 0xFF); out[pos + 3] = (byte) ((value >> 0) & 0xFF); - return pos + 4; + return pos + INTEGER_BYTE_COUNT; } private int writeBytes(byte[] out, int pos, byte[] value) { diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png Binary files differindex 3137e7ee6e6f..908056fa1fd9 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png Binary files differindex f4e741bf275b..58843bbbc8e7 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png Binary files differindex fb45ffcdf4bc..66cd57bcb537 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png Binary files differindex ffffb2daac05..fc8dee1a6bef 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png Binary files differindex 21177050e88e..4a5d001fb557 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png Binary files differindex ba2d78a54742..ed31e8e9c071 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png Binary files differindex 11028463f3e6..6583878e5ebe 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png Binary files differindex b429222e2d67..69f3543d3a54 100644 --- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png +++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png Binary files differindex 5c98614016f8..9820a79d0bc9 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png Binary files differindex a67c02ff6e21..cc65b07e8afd 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png Binary files differindex 1a5cba354ec1..d0404bf158ae 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png Binary files differindex 4931b66e6b1e..4b0a74f24375 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png Binary files differindex f288d9f2001a..53a73646f8a5 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png Binary files differindex 664903103628..06b3913ee241 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png Binary files differindex 1b57936424c0..4f23daeea604 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png Binary files differindex f5f2f7032db3..fb3098279da9 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png Binary files differindex 7c6b8e5189e1..0b41317e4484 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png Binary files differindex 50c04bfed471..5c9c0e5f6fda 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png Binary files differindex d59212902acb..4db9e9d8d3e3 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png Binary files differindex 6abc7c8ee999..19ad300d30e7 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png Binary files differindex 738bd217b7df..524b31bea1a3 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png Binary files differindex fb691fcdbfa3..fdd640c4ebb0 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png Binary files differindex 0c7ba35ad5a6..a1a0646437e2 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png diff --git a/packages/SystemUI/res/drawable/notification_row_bg.xml b/packages/SystemUI/res/drawable/notification_row_bg.xml new file mode 100644 index 000000000000..dc626d18163c --- /dev/null +++ b/packages/SystemUI/res/drawable/notification_row_bg.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android" + android:exitFadeDuration="@android:integer/config_mediumAnimTime"> + + <item android:state_pressed="true" android:drawable="@android:color/holo_blue_light" /> + <item android:state_pressed="false" android:drawable="@drawable/notification_item_background_color" /> +</selector> diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index ff8687838cf3..3220e62d3075 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -23,6 +23,7 @@ android:layout_alignParentLeft="true" android:scaleType="center" android:clickable="true" + android:background="@*android:drawable/notify_panel_notification_icon_bg_tile" /> <com.android.systemui.statusbar.LatestItemView android:id="@+id/content" @@ -33,14 +34,14 @@ android:layout_alignParentRight="true" android:focusable="true" android:clickable="true" - android:background="@drawable/notification_item_background_color" + android:background="@drawable/notification_row_bg" /> <View android:layout_width="match_parent" android:layout_height="@dimen/notification_divider_height" android:layout_alignParentBottom="true" - android:background="@drawable/status_bar_notification_row_background_color" + android:background="@drawable/notification_item_background_color" /> </RelativeLayout> diff --git a/packages/SystemUI/res/layout/status_bar_tracking.xml b/packages/SystemUI/res/layout/status_bar_tracking.xml index 25c0237dad31..c1b00668429f 100644 --- a/packages/SystemUI/res/layout/status_bar_tracking.xml +++ b/packages/SystemUI/res/layout/status_bar_tracking.xml @@ -26,12 +26,21 @@ android:paddingRight="0px" > - <View - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_weight="1" - android:background="@drawable/notification_tracking_bg" - /> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:background="@drawable/notification_tracking_bg" + > + <com.android.systemui.statusbar.phone.CarrierLabel + android:textAppearance="@style/TextAppearance.StatusBar.Clock" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_gravity="bottom" + android:gravity="center" + android:paddingBottom="20dp" + /> + </FrameLayout> <com.android.systemui.statusbar.phone.CloseDragHandle android:id="@+id/close" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/values-ar-xlarge/strings.xml b/packages/SystemUI/res/values-ar-xlarge/strings.xml deleted file mode 100644 index d4fb8738fc1d..000000000000 --- a/packages/SystemUI/res/values-ar-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"محو الكل"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"لا اتصال بالإنترنت"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi متصل"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"جارٍ البحث عن GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"تم تعيين الموقع بواسطة GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"إيقاف التنبيهات"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"انقر هنا لإعادة تشغيل التنبيهات."</string> -</resources> diff --git a/packages/SystemUI/res/values-bg-xlarge/strings.xml b/packages/SystemUI/res/values-bg-xlarge/strings.xml deleted file mode 100644 index 4e730aefac24..000000000000 --- a/packages/SystemUI/res/values-bg-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Изчистване"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Няма връзка с интернет"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: има връзка"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Търси се GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Местоположението е зададено от GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Известията са изключени"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Докоснете тук, за да включите отново известията."</string> -</resources> diff --git a/packages/SystemUI/res/values-ca-xlarge/strings.xml b/packages/SystemUI/res/values-ca-xlarge/strings.xml deleted file mode 100644 index 9fc74d0ca1e9..000000000000 --- a/packages/SystemUI/res/values-ca-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Esborra-ho"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"No connexió Internet"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: connectat"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"S\'està cercant un GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"S\'ha establert la ubicació per GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notificacions desactivades"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Pica aquí per tornar a activar les notificacions."</string> -</resources> diff --git a/packages/SystemUI/res/values-cs-xlarge/strings.xml b/packages/SystemUI/res/values-cs-xlarge/strings.xml deleted file mode 100644 index 05b12482a299..000000000000 --- a/packages/SystemUI/res/values-cs-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Vymazat vše"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Žádné připojení"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: připojeno"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Vyhledávání satelitů GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Poloha nastavena pomocí GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Oznámení jsou vypnuta"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Chcete-li oznámení znovu zapnout, klepněte sem."</string> -</resources> diff --git a/packages/SystemUI/res/values-da-xlarge/strings.xml b/packages/SystemUI/res/values-da-xlarge/strings.xml deleted file mode 100644 index dd20e6458a1c..000000000000 --- a/packages/SystemUI/res/values-da-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Ryd alt"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Ingen internetforb."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi er forbundet"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Søger efter GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Placeringen er angivet ved hjælp af GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Meddelelser: Fra"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Tryk her for at slå meddelelser til igen."</string> -</resources> diff --git a/packages/SystemUI/res/values-de-xlarge/strings.xml b/packages/SystemUI/res/values-de-xlarge/strings.xml deleted file mode 100644 index cc782dad36cf..000000000000 --- a/packages/SystemUI/res/values-de-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Alle löschen"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Keine Internetverbindung"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Mit WLAN verbunden"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Suche nach GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Standort durch GPS festgelegt"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Benachrichtigungen aus"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Tippen Sie hier, um Benachrichtigungen wieder einzuschalten."</string> -</resources> diff --git a/packages/SystemUI/res/values-el-xlarge/strings.xml b/packages/SystemUI/res/values-el-xlarge/strings.xml deleted file mode 100644 index 4f7814a925b8..000000000000 --- a/packages/SystemUI/res/values-el-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Διαγ. όλων"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Χωρίς σύνδ. σε Διαδ."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: συνδέθηκε"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Αναζήτηση για GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Ρύθμιση τοποθεσίας με GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Ειδοποιήσεις ανενεργές"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Πατήστε εδώ για να ενεργοποιήσετε τις ειδοποιήσεις"</string> -</resources> diff --git a/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml b/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml deleted file mode 100644 index 68986f087865..000000000000 --- a/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Clear all"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"No Internet connection"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi connected"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Searching for GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Location set by GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notifications off"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Tap here to turn notifications back on."</string> -</resources> diff --git a/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml b/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml deleted file mode 100644 index fa9b76242c6c..000000000000 --- a/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Eliminar todos"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Sin conexión a Int."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"WiFi conectado"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Buscando GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"La ubicación se estableció por GPS."</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notificaciones desactivadas"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Presiona aquí para volver a activar las notificaciones."</string> -</resources> diff --git a/packages/SystemUI/res/values-es-xlarge/strings.xml b/packages/SystemUI/res/values-es-xlarge/strings.xml deleted file mode 100644 index a7588da5b9fa..000000000000 --- a/packages/SystemUI/res/values-es-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Borrar todo"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Sin conexión a Internet"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Con conexión WiFi"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Buscando GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Ubicación definida por GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notificaciones desactivadas"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Toca aquí para volver a activar las notificaciones."</string> -</resources> diff --git a/packages/SystemUI/res/values-fa-xlarge/strings.xml b/packages/SystemUI/res/values-fa-xlarge/strings.xml deleted file mode 100644 index a8e25430e697..000000000000 --- a/packages/SystemUI/res/values-fa-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"پاک کردن همه"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"اتصال اینترنت موجود نیست"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi متصل شد"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"جستجوی GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"مکان تنظیم شده توسط GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"اعلان ها خاموش"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"برای روشن کردن مجدد اعلان ها، اینجا را ضربه بزنید."</string> -</resources> diff --git a/packages/SystemUI/res/values-fi-xlarge/strings.xml b/packages/SystemUI/res/values-fi-xlarge/strings.xml deleted file mode 100644 index 754c577a7e6d..000000000000 --- a/packages/SystemUI/res/values-fi-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Poista kaikki"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Ei internetyhteyttä"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wifi yhdistetty"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Haetaan GPS-yhteyttä"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Sijainti määritetty GPS:n avulla"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Ilmoitukset pois käytöstä"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Ota ilmoitukset uudelleen käyttöön napauttamalla tätä."</string> -</resources> diff --git a/packages/SystemUI/res/values-fr-xlarge/strings.xml b/packages/SystemUI/res/values-fr-xlarge/strings.xml deleted file mode 100644 index 08f673d5d855..000000000000 --- a/packages/SystemUI/res/values-fr-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Tout effacer"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Aucune connexion Internet"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Connecté au Wi-Fi"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Recherche de GPS en cours"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Position définie par GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notifications désactivées"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Appuyez ici pour réactiver les notifications."</string> -</resources> diff --git a/packages/SystemUI/res/values-hr-xlarge/strings.xml b/packages/SystemUI/res/values-hr-xlarge/strings.xml deleted file mode 100644 index b6e15dc66862..000000000000 --- a/packages/SystemUI/res/values-hr-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Izbriši sve"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nema int. veze"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: povezano"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Pretraživanje GPS-a"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokaciju utvrdio GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Obavijesti isključene"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Dotaknite ovdje da biste ponovo uključili obavijesti."</string> -</resources> diff --git a/packages/SystemUI/res/values-hu-xlarge/strings.xml b/packages/SystemUI/res/values-hu-xlarge/strings.xml deleted file mode 100644 index fe2e5ee0f6dc..000000000000 --- a/packages/SystemUI/res/values-hu-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Össz.törl."</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nincs internetkapcs."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi csatlakozva"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS keresése"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"A GPS beállította a helyet"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Értesítések kikapcsolva"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Itt érintse meg az értesítések bekapcsolásához."</string> -</resources> diff --git a/packages/SystemUI/res/values-in-xlarge/strings.xml b/packages/SystemUI/res/values-in-xlarge/strings.xml deleted file mode 100644 index a4ca3416a0ad..000000000000 --- a/packages/SystemUI/res/values-in-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Hapus semua"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Tidak ada sambungan internet"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi tersambung"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Menelusuri GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokasi yang disetel oleh GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Pemberitahuan mati"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Ketuk di sini untuk menghidupkan lagi pemberitahuan."</string> -</resources> diff --git a/packages/SystemUI/res/values-it-xlarge/strings.xml b/packages/SystemUI/res/values-it-xlarge/strings.xml deleted file mode 100644 index 24d88744938a..000000000000 --- a/packages/SystemUI/res/values-it-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Canc. tutto"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"No connessione Internet"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: connesso"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Ricerca del GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Posizione stabilita dal GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notifiche disattivate"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Tocca qui per riattivare le notifiche."</string> -</resources> diff --git a/packages/SystemUI/res/values-iw-xlarge/strings.xml b/packages/SystemUI/res/values-iw-xlarge/strings.xml deleted file mode 100644 index 97172b80261e..000000000000 --- a/packages/SystemUI/res/values-iw-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"נקה הכל"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"אין חיבור לאינטרנט"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi מחובר"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"מחפש GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"מיקום מוגדר על ידי GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"מצב התראות כבוי"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"הקש כאן כדי להפעיל מחדש את ההתראות."</string> -</resources> diff --git a/packages/SystemUI/res/values-ja-xlarge/strings.xml b/packages/SystemUI/res/values-ja-xlarge/strings.xml deleted file mode 100644 index e67e0e1e3c76..000000000000 --- a/packages/SystemUI/res/values-ja-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"すべて消去"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"インターネット未接続"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi接続済み"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"GPSで検索中"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"GPSにより現在地が設定されました"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"通知OFF"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"通知を有効にするにはここをタップします。"</string> -</resources> diff --git a/packages/SystemUI/res/values-ko-xlarge/strings.xml b/packages/SystemUI/res/values-ko-xlarge/strings.xml deleted file mode 100644 index e28ac63e9459..000000000000 --- a/packages/SystemUI/res/values-ko-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"모두 지우기"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"인터넷에 연결되지 않음"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 연결됨"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS 검색"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS에서 설정한 위치"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"알림 사용 안함"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"알림을 다시 사용하려면 여기를 누르세요."</string> -</resources> diff --git a/packages/SystemUI/res/values-lt-xlarge/strings.xml b/packages/SystemUI/res/values-lt-xlarge/strings.xml deleted file mode 100644 index 12e8bb349da0..000000000000 --- a/packages/SystemUI/res/values-lt-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Išv. viską"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nėra interneto ryšio"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Prisijungta prie „Wi-Fi“"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Ieškoma GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS nustatyta vieta"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Pranešimai išjungti"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Palieskite čia, kad vėl įjungtumėte pranešimus."</string> -</resources> diff --git a/packages/SystemUI/res/values-lv-xlarge/strings.xml b/packages/SystemUI/res/values-lv-xlarge/strings.xml deleted file mode 100644 index aecb4715e459..000000000000 --- a/packages/SystemUI/res/values-lv-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Notīr.visu"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nav interneta sav."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Izv. sav. ar Wi-Fi"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Notiek GPS meklēšana..."</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS iestatītā atrašanās vieta"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Paziņojumi ir izslēgti."</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Pieskarieties šeit, lai vēlreiz ieslēgtu paziņojumus."</string> -</resources> diff --git a/packages/SystemUI/res/values-nb-xlarge/strings.xml b/packages/SystemUI/res/values-nb-xlarge/strings.xml deleted file mode 100644 index 717ee79f017e..000000000000 --- a/packages/SystemUI/res/values-nb-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Tøm alt"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Ingen Int.-tilkobl."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: tilkoblet"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Søker etter GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Posisjon angitt av GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Varslinger er slått av"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Trykk her for å slå på varslinger igjen."</string> -</resources> diff --git a/packages/SystemUI/res/values-nl-xlarge/strings.xml b/packages/SystemUI/res/values-nl-xlarge/strings.xml deleted file mode 100644 index 7c84a7a01f3e..000000000000 --- a/packages/SystemUI/res/values-nl-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Wissen"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Geen internetverb."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Verbonden via Wi-Fi"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Zoeken naar GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Locatie bepaald met GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Meldingen uit"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Tik hier om meldingen weer in te schakelen."</string> -</resources> diff --git a/packages/SystemUI/res/values-pl-xlarge/strings.xml b/packages/SystemUI/res/values-pl-xlarge/strings.xml deleted file mode 100644 index 9db1cab823ec..000000000000 --- a/packages/SystemUI/res/values-pl-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Wyczyść wszystko"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Brak połączenia internetowego"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: połączono"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Wyszukiwanie sygnału GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokalizacja ustawiona wg GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Powiadomienia wyłączone"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Dotknij tutaj, aby z powrotem włączyć powiadomienia."</string> -</resources> diff --git a/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml b/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml deleted file mode 100644 index 7860208e3ae1..000000000000 --- a/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Limpar tudo"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Sem ligação internet"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi ligado"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"A procurar GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Localização definida por GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notificações desativadas"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Toque aqui para voltar a ativar as notificações."</string> -</resources> diff --git a/packages/SystemUI/res/values-pt-xlarge/strings.xml b/packages/SystemUI/res/values-pt-xlarge/strings.xml deleted file mode 100644 index 2a1786d7c460..000000000000 --- a/packages/SystemUI/res/values-pt-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Limpar tudo"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Sem conex. à inter."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi conectado"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Procurando GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Localização definida por GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notificações desativadas"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Toque aqui para ativar novamente as notificações."</string> -</resources> diff --git a/packages/SystemUI/res/values-ro-xlarge/strings.xml b/packages/SystemUI/res/values-ro-xlarge/strings.xml deleted file mode 100644 index 21fd0ad7ae4e..000000000000 --- a/packages/SystemUI/res/values-ro-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Şterg. tot"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Fără conex. internet"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi conectat"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Se caută dispozitivul GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Locaţie setată prin GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Notificările sunt dezactivate"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Apăsaţi aici pentru a reactiva notificările."</string> -</resources> diff --git a/packages/SystemUI/res/values-ru-xlarge/strings.xml b/packages/SystemUI/res/values-ru-xlarge/strings.xml deleted file mode 100644 index bc31fb1250b7..000000000000 --- a/packages/SystemUI/res/values-ru-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Удалить все"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Нет подключения"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi подкл."</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Выполняется поиск при помощи GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Местоположение установлено при помощи GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Показ уведомлений отключен"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Нажмите здесь, чтобы снова включить показ уведомлений."</string> -</resources> diff --git a/packages/SystemUI/res/values-sk-xlarge/strings.xml b/packages/SystemUI/res/values-sk-xlarge/strings.xml deleted file mode 100644 index ee9e61301c61..000000000000 --- a/packages/SystemUI/res/values-sk-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Vymazať všetky"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nepripoj. k Intern."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: pripojené"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Hľadanie signálu GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Poloha určená pomocou GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Upozornenia sú vypnuté"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Klepnutím tu upozornenia znova povolíte."</string> -</resources> diff --git a/packages/SystemUI/res/values-sl-xlarge/strings.xml b/packages/SystemUI/res/values-sl-xlarge/strings.xml deleted file mode 100644 index 57ed9a722f52..000000000000 --- a/packages/SystemUI/res/values-sl-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Izbriši vse"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Brez inter. povez."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi – povezano"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Iskanje GPS-a"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokacija nastavljena z GPS-om"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Obvestila izklopljena"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Tapnite tukaj, da spet vklopite obvestila."</string> -</resources> diff --git a/packages/SystemUI/res/values-sr-xlarge/strings.xml b/packages/SystemUI/res/values-sr-xlarge/strings.xml deleted file mode 100644 index 95fbc2f08e3c..000000000000 --- a/packages/SystemUI/res/values-sr-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Обриши све"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Нема интернет везе"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi је повезан"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Тражи се GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Локацију је подесио GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Обавештења су искључена"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Додирните овде да бисте поново укључили обавештења."</string> -</resources> diff --git a/packages/SystemUI/res/values-sv-xlarge/strings.xml b/packages/SystemUI/res/values-sv-xlarge/strings.xml deleted file mode 100644 index ce608c20e49f..000000000000 --- a/packages/SystemUI/res/values-sv-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Ta bort alla"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Ingen Internetansl."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi-ansluten"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Sökning efter GPS pågår"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Platsen har identifierats av GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Aviseringar inaktiverade"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Knacka lätt här om du vill aktivera aviseringar igen."</string> -</resources> diff --git a/packages/SystemUI/res/values-th-xlarge/strings.xml b/packages/SystemUI/res/values-th-xlarge/strings.xml deleted file mode 100644 index 824de38e4244..000000000000 --- a/packages/SystemUI/res/values-th-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"ล้างหมด"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"ไม่มีการเชื่อมต่ออินเทอร์เน็ต"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"เชื่อมต่อ Wi-Fi แล้ว"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"การค้นหาสำหรับ GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"ตำแหน่งที่กำหนดโดย GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"การแจ้งเตือนปิดอยู่"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"แตะที่นี่เพื่อเปิดการแจ้งเตือนอีกครั้ง"</string> -</resources> diff --git a/packages/SystemUI/res/values-tl-xlarge/strings.xml b/packages/SystemUI/res/values-tl-xlarge/strings.xml deleted file mode 100644 index 582adbc56b46..000000000000 --- a/packages/SystemUI/res/values-tl-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"I-clear lahat"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Wala net connection"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Konektado ang WiFi"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Naghahanap ng GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokasyon na itinatakda ng GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Naka-off ang mga notification"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Mag-tap dito upang i-on muli ang mga notification."</string> -</resources> diff --git a/packages/SystemUI/res/values-tr-xlarge/strings.xml b/packages/SystemUI/res/values-tr-xlarge/strings.xml deleted file mode 100644 index 6db515f2db47..000000000000 --- a/packages/SystemUI/res/values-tr-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Tümünü temizle"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"İnternet bağlnts yok"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Kablosuz bağlandı"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS aranıyor"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Konum GPS ile belirlendi"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Bildirimler kapalı"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Bildirimleri tekrar açmak için buraya hafifçe vurun."</string> -</resources> diff --git a/packages/SystemUI/res/values-uk-xlarge/strings.xml b/packages/SystemUI/res/values-uk-xlarge/strings.xml deleted file mode 100644 index 81e50c094f3c..000000000000 --- a/packages/SystemUI/res/values-uk-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Очист. все"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Інтернет не під\'єдн."</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi під\'єднано"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Виконується пошук за допомогою GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Місцезнаходження встановлено за допомогою GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Сповіщення вимкнено"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Торкніться тут, щоб знову ввімкнути сповіщення."</string> -</resources> diff --git a/packages/SystemUI/res/values-vi-xlarge/strings.xml b/packages/SystemUI/res/values-vi-xlarge/strings.xml deleted file mode 100644 index 6382fae4d951..000000000000 --- a/packages/SystemUI/res/values-vi-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Xóa tất cả"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Không có kết nối Internet"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Đã kết nối Wi-Fi"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"Tìm kiếm GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"Vị trí đặt bởi GPS"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"Tắt thông báo"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"Chạm vào đây để bật lại thông báo."</string> -</resources> diff --git a/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml b/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml deleted file mode 100644 index 207ebe464dc0..000000000000 --- a/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"全部清除"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"未连接至互联网"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 已连接"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"正在搜索 GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS 设置的位置"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"通知已关闭"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"点按此处可以重新打开通知。"</string> -</resources> diff --git a/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml b/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml deleted file mode 100644 index 14a10f286cdb..000000000000 --- a/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright (c) 2010, 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. - */ - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="status_bar_clear_all_button" msgid="4722520806446512408">"全部清除"</string> - <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"沒有網路連線"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 已連線"</string> - <string name="gps_notification_searching_text" msgid="894185519046488403">"正在搜尋 GPS"</string> - <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS 已定位"</string> - <string name="notifications_off_title" msgid="2297252328026582111">"關閉通知"</string> - <string name="notifications_off_text" msgid="3754847213329718358">"輕觸這裡即可重新開啟通知。"</string> -</resources> diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 492f3c245349..bf1ec257856f 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -26,6 +26,7 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.Region.Op; import android.opengl.GLUtils; +import android.os.SystemProperties; import android.renderscript.Matrix4f; import android.service.wallpaper.WallpaperService; import android.util.Log; @@ -56,6 +57,7 @@ public class ImageWallpaper extends WallpaperService { private static final String TAG = "ImageWallpaper"; private static final String GL_LOG_TAG = "ImageWallpaperGL"; private static final boolean DEBUG = false; + private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu"; static final boolean FIXED_SIZED_SURFACE = true; static final boolean USE_OPENGL = true; @@ -71,12 +73,19 @@ public class ImageWallpaper extends WallpaperService { //noinspection PointlessBooleanExpression,ConstantConditions if (FIXED_SIZED_SURFACE && USE_OPENGL) { - WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); - Display display = windowManager.getDefaultDisplay(); - mIsHwAccelerated = ActivityManager.isHighEndGfx(display); + if (!isEmulator()) { + WindowManager windowManager = + (WindowManager) getSystemService(Context.WINDOW_SERVICE); + Display display = windowManager.getDefaultDisplay(); + mIsHwAccelerated = ActivityManager.isHighEndGfx(display); + } } } + private static boolean isEmulator() { + return "1".equals(SystemProperties.get(PROPERTY_KERNEL_QEMU, "0")); + } + public Engine onCreateEngine() { return new DrawableEngine(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java index 37c77f6e67e4..595953740633 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java @@ -118,7 +118,7 @@ public abstract class StatusBar extends SystemUI implements CommandQueue.Callbac WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.RGBX_8888); + PixelFormat.OPAQUE); // the status bar should be in an overlay if possible final Display defaultDisplay diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index a90eb3fa9217..69978378d140 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -29,6 +29,7 @@ import android.util.Slog; import android.util.Log; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; +import android.widget.ImageView; import java.text.NumberFormat; @@ -70,6 +71,8 @@ public class StatusBarIconView extends AnimatedImageView { final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); setAlpha(alpha); } + + setScaleType(ImageView.ScaleType.CENTER); } private static boolean streq(String a, String b) { 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 8fc844882334..e5d4d22742f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -316,12 +316,7 @@ public class PhoneStatusBar extends StatusBar { } // figure out which pixel-format to use for the status bar. - mPixelFormat = PixelFormat.TRANSLUCENT; - Drawable bg = sb.getBackground(); - if (bg != null) { - mPixelFormat = bg.getOpacity(); - } - + mPixelFormat = PixelFormat.OPAQUE; mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons); mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons); mIcons = (LinearLayout)sb.findViewById(R.id.icons); @@ -896,14 +891,6 @@ public class PhoneStatusBar extends StatusBar { } } - void workAroundBadLayerDrawableOpacity(View v) { - LayerDrawable d = (LayerDrawable)v.getBackground(); - if (d == null) return; - v.setBackgroundDrawable(null); - d.setOpacity(PixelFormat.TRANSLUCENT); - v.setBackgroundDrawable(d); - } - private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) { StatusBarNotification sbn = entry.notification; RemoteViews remoteViews = sbn.notification.contentView; @@ -915,7 +902,6 @@ public class PhoneStatusBar extends StatusBar { LayoutInflater inflater = (LayoutInflater)mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false); - workAroundBadLayerDrawableOpacity(row); View vetoButton = row.findViewById(R.id.veto); if (entry.notification.isClearable()) { final String _pkg = sbn.pkg; @@ -1608,6 +1594,9 @@ public class PhoneStatusBar extends StatusBar { // the user switches to home. We know it is safe to do at this // point, so make sure new activity switches are now allowed. ActivityManagerNative.getDefault().resumeAppSwitches(); + // Also, notifications can be launched from the lock screen, + // so dismiss the lock screen when the activity starts. + ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); } catch (RemoteException e) { } @@ -2031,8 +2020,13 @@ public class PhoneStatusBar extends StatusBar { // The user is not allowed to get stuck without navigation UI. Upon the slightest user // interaction we bring the navigation back. public void userActivity() { - if (mNavigationBarView != null) { - mNavigationBarView.setHidden(false); + if (0 != (mSystemUiVisibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) { + try { + mBarService.setSystemUiVisibility( + mSystemUiVisibility & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); + } catch (RemoteException ex) { + // weep softly + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 05e171c1c07c..9bee5dfca017 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -64,6 +64,8 @@ public class PhoneStatusBarPolicy { private static final int INET_CONDITION_THRESHOLD = 50; + private static final boolean SHOW_SYNC_ICON = false; + private final Context mContext; private final StatusBarManager mService; private final Handler mHandler = new Handler(); @@ -195,6 +197,7 @@ public class PhoneStatusBarPolicy { } private final void updateSyncState(Intent intent) { + if (!SHOW_SYNC_ICON) return; boolean isActive = intent.getBooleanExtra("active", false); boolean isFailing = intent.getBooleanExtra("failing", false); mService.setIconVisibility("sync_active", isActive); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 0dfc4f7a55ba..a98d519ff9d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -720,28 +720,19 @@ public class NetworkController extends BroadcastReceiver { Slog.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus); } - int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); - - switch (info.getType()) { - case ConnectivityManager.TYPE_MOBILE: - mInetCondition = inetCondition; - updateDataNetType(); - updateDataIcon(); - updateTelephonySignalStrength(); // apply any change in connectionStatus - break; - case ConnectivityManager.TYPE_WIFI: - mInetCondition = inetCondition; - updateWifiIcons(); - break; - case ConnectivityManager.TYPE_BLUETOOTH: - mInetCondition = inetCondition; - if (info != null) { - mBluetoothTethered = info.isConnected() ? true: false; - } else { - mBluetoothTethered = false; - } - break; + mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); + + if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) { + mBluetoothTethered = info.isConnected() ? true: false; + } else { + mBluetoothTethered = false; } + + // We want to update all the icons, all at once, for any condition change + updateDataNetType(); + updateDataIcon(); + updateTelephonySignalStrength(); + updateWifiIcons(); } @@ -795,6 +786,7 @@ public class NetworkController extends BroadcastReceiver { mWifiActivityIconId = R.drawable.stat_sys_wifi_inout; break; case WifiManager.DATA_ACTIVITY_NONE: + mWifiActivityIconId = 0; break; } } @@ -1035,8 +1027,8 @@ public class NetworkController extends BroadcastReceiver { pw.println(mWifiLevel); pw.print(" mWifiSsid="); pw.println(mWifiSsid); - pw.print(" mWifiIconId="); - pw.println(mWifiIconId); + pw.print(String.format(" mWifiIconId=0x%08x/%s", + mWifiIconId, getResourceName(mWifiIconId))); pw.print(" mWifiActivity="); pw.println(mWifiActivity); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index c2f07d63f13e..435aa8c05d61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -1308,6 +1308,9 @@ public class TabletStatusBar extends StatusBar implements // the user switches to home. We know it is safe to do at this // point, so make sure new activity switches are now allowed. ActivityManagerNative.getDefault().resumeAppSwitches(); + // Also, notifications can be launched from the lock screen, + // so dismiss the lock screen when the activity starts. + ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); } catch (RemoteException e) { } diff --git a/packages/VpnDialogs/res/layout/confirm.xml b/packages/VpnDialogs/res/layout/confirm.xml index 11a247a633aa..fef00c2203b4 100644 --- a/packages/VpnDialogs/res/layout/confirm.xml +++ b/packages/VpnDialogs/res/layout/confirm.xml @@ -15,46 +15,43 @@ limitations under the License. --> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:padding="3mm"> - - <ImageView android:id="@+id/icon" - android:layout_width="@android:dimen/app_icon_size" - android:layout_height="@android:dimen/app_icon_size" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true" - android:layout_marginRight="1mm"/> - - <TextView android:id="@+id/warning" - android:layout_width="fill_parent" +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentRight="true" - android:layout_below="@id/icon" - android:padding="3mm" - android:text="@string/warning" - android:textSize="18sp"/> - - <TextView android:id="@+id/prompt" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_alignParentRight="true" - android:layout_toRightOf="@id/icon" - android:layout_above="@id/warning" - android:gravity="center_vertical" - android:textSize="20sp"/> - - <CheckBox android:id="@+id/check" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentRight="true" - android:layout_below="@id/warning" - android:text="@string/accept" - android:textSize="20sp" - android:checked="false"/> - -</RelativeLayout> + android:orientation="vertical" + android:padding="3mm"> + + <LinearLayout android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center_vertical"> + + <ImageView android:id="@+id/icon" + android:layout_width="@android:dimen/app_icon_size" + android:layout_height="@android:dimen/app_icon_size" + android:paddingRight="1mm"/> + + <TextView android:id="@+id/prompt" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:textSize="18sp"/> + </LinearLayout> + + <TextView android:id="@+id/warning" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingTop="1mm" + android:paddingBottom="1mm" + android:text="@string/warning" + android:textSize="18sp"/> + + <CheckBox android:id="@+id/check" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/accept" + android:textSize="20sp" + android:checked="false"/> + </LinearLayout> +</ScrollView> diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java index d668e98f0f27..7fb141709884 100644 --- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java +++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java @@ -181,8 +181,10 @@ public class ManageDialog extends Activity implements Handler.Callback, String line = in.readLine().trim(); if (line.startsWith(prefix)) { String[] numbers = line.substring(prefix.length()).split(" +"); - if (numbers.length == 17) { - return numbers; + for (int i = 1; i < 17; ++i) { + if (!numbers[i].equals("0")) { + return numbers; + } } break; } diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java index 6ff9a608ad44..a4baeed24c2a 100644 --- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java @@ -54,7 +54,7 @@ import java.io.IOException; public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen, View.OnClickListener, TextWatcher { private static final String LOCK_PATTERN_PACKAGE = "com.android.settings"; - private static final String LOCK_PATTERN_CLASS = LOCK_PATTERN_PACKAGE + ".ChooseLockPattern"; + private static final String LOCK_PATTERN_CLASS = LOCK_PATTERN_PACKAGE + ".ChooseLockGeneric"; /** * The amount of millis to stay awake once this screen detects activity @@ -112,7 +112,7 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree mUpdateMonitor = updateMonitor; mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor, - lockPatternUtils, callback); + lockPatternUtils, callback, true); } public void afterTextChanged(Editable s) { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java index 8654a25d2f89..24dce1a0dd79 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java @@ -58,6 +58,7 @@ class KeyguardStatusViewManager implements OnClickListener { private static final int CARRIER_HELP_TEXT = 12; private static final int HELP_MESSAGE_TEXT = 13; private static final int OWNER_INFO = 14; + private static final int BATTERY_INFO = 15; private StatusMode mStatus; private String mDateFormatString; @@ -84,10 +85,13 @@ class KeyguardStatusViewManager implements OnClickListener { // last known battery level private int mBatteryLevel = 100; + // last known SIM state + protected State mSimState; + private LockPatternUtils mLockPatternUtils; private KeyguardUpdateMonitor mUpdateMonitor; private Button mEmergencyCallButton; - private boolean mShouldEnableUnlock; + private boolean mUnlockDisabledDueToSimState; // Shadowed text values private CharSequence mCarrierText; @@ -97,7 +101,9 @@ class KeyguardStatusViewManager implements OnClickListener { private CharSequence mOwnerInfoText; private boolean mShowingStatus; private KeyguardScreenCallback mCallback; - private boolean mHideEmergencyCallButton = false; + private final boolean mShowEmergencyButtonByDefault; + private CharSequence mPlmn; + private CharSequence mSpn; private class TransientTextManager { private TextView mTextView; @@ -149,7 +155,9 @@ class KeyguardStatusViewManager implements OnClickListener { }; public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor, - LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback) { + LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback, + boolean showEmergencyButtonByDefault) { + if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()"); mContainer = view; mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year); mLockPatternUtils = lockPatternUtils; @@ -163,6 +171,13 @@ class KeyguardStatusViewManager implements OnClickListener { mOwnerInfoView = (TextView) findViewById(R.id.propertyOf); mTransportView = (TransportControlView) findViewById(R.id.transport); mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton); + mShowEmergencyButtonByDefault = showEmergencyButtonByDefault; + + // Hide transport control view until we know we need to show it. + if (mTransportView != null) { + mTransportView.setVisibility(View.GONE); + } + if (mEmergencyCallButton != null) { mEmergencyCallButton.setText(R.string.lockscreen_emergency_call); mEmergencyCallButton.setOnClickListener(this); @@ -171,8 +186,6 @@ class KeyguardStatusViewManager implements OnClickListener { mTransientTextManager = new TransientTextManager(mCarrierView); - updateEmergencyCallButtonState(); - resetStatusInfo(); refreshDate(); updateOwnerInfo(); @@ -185,10 +198,6 @@ class KeyguardStatusViewManager implements OnClickListener { v.setSelected(true); } } - - // until we get an update... - setCarrierText(LockPatternUtils.getCarrierString( - mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn())); } private boolean inWidgetMode() { @@ -246,6 +255,7 @@ class KeyguardStatusViewManager implements OnClickListener { case INSTRUCTION_TEXT: case CARRIER_HELP_TEXT: case HELP_MESSAGE_TEXT: + case BATTERY_INFO: mTransientTextManager.post(string, 0, INSTRUCTION_RESET_DELAY); break; @@ -260,15 +270,16 @@ class KeyguardStatusViewManager implements OnClickListener { } public void onPause() { + if (DEBUG) Log.v(TAG, "onPause()"); mUpdateMonitor.removeCallback(mInfoCallback); mUpdateMonitor.removeCallback(mSimStateCallback); } /** {@inheritDoc} */ public void onResume() { + if (DEBUG) Log.v(TAG, "onResume()"); mUpdateMonitor.registerInfoCallback(mInfoCallback); mUpdateMonitor.registerSimStateCallback(mSimStateCallback); - updateEmergencyCallButtonState(); resetStatusInfo(); } @@ -393,15 +404,16 @@ class KeyguardStatusViewManager implements OnClickListener { } } - boolean shouldEnableUnlock() { - return mShouldEnableUnlock; - } - /** * Determine the current status of the lock screen given the sim state and other stuff. */ public StatusMode getStatusForIccState(IccCard.State simState) { - boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned() + // Since reading the SIM may take a while, we assume it is present until told otherwise. + if (simState == null) { + return StatusMode.Normal; + } + + final boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned() && (simState == IccCard.State.ABSENT || simState == IccCard.State.PERM_DISABLED)); // Assume we're NETWORK_LOCKED if not provisioned @@ -437,23 +449,21 @@ class KeyguardStatusViewManager implements OnClickListener { * * @param simState */ - private void updateWithSimStatus(State simState) { - // The emergency call button no longer appears on this screen. - if (DEBUG) Log.d(TAG, "updateLayout: status=" + mStatus); + private void updateCarrierTextWithSimStatus(State simState) { + if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState); CharSequence carrierText = null; int carrierHelpTextId = 0; - mShouldEnableUnlock = true; + mUnlockDisabledDueToSimState = false; mStatus = getStatusForIccState(simState); - + mSimState = simState; switch (mStatus) { case Normal: - carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(), - mUpdateMonitor.getTelephonySpn()); + carrierText = makeCarierString(mPlmn, mSpn); break; case NetworkLocked: - carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(), + carrierText = makeCarierString(mPlmn, getContext().getText(R.string.lockscreen_network_locked_message)); carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled; break; @@ -466,32 +476,32 @@ class KeyguardStatusViewManager implements OnClickListener { case SimPermDisabled: carrierText = getContext().getText(R.string.lockscreen_missing_sim_message_short); carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions; + mUnlockDisabledDueToSimState = true; break; case SimMissingLocked: - carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(), + carrierText = makeCarierString(mPlmn, getContext().getText(R.string.lockscreen_missing_sim_message_short)); carrierHelpTextId = R.string.lockscreen_missing_sim_instructions; - mShouldEnableUnlock = false; + mUnlockDisabledDueToSimState = true; break; case SimLocked: - carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(), + carrierText = makeCarierString(mPlmn, getContext().getText(R.string.lockscreen_sim_locked_message)); break; case SimPukLocked: - carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(), + carrierText = makeCarierString(mPlmn, getContext().getText(R.string.lockscreen_sim_puk_locked_message)); if (!mLockPatternUtils.isPukUnlockScreenEnable()) { - mShouldEnableUnlock = false; + mUnlockDisabledDueToSimState = true; } break; } setCarrierText(carrierText); setCarrierHelpText(carrierHelpTextId); - updateEmergencyCallButtonState(); } private View findViewById(int id) { @@ -554,12 +564,11 @@ class KeyguardStatusViewManager implements OnClickListener { } } - private void updateEmergencyCallButtonState() { + private void updateEmergencyCallButtonState(int phoneState) { if (mEmergencyCallButton != null) { - mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); - if (mHideEmergencyCallButton) { - mEmergencyCallButton.setVisibility(View.GONE); - } + boolean showIfCapable = mShowEmergencyButtonByDefault || mUnlockDisabledDueToSimState; + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton, + phoneState, showIfCapable); } } @@ -571,7 +580,8 @@ class KeyguardStatusViewManager implements OnClickListener { mShowingBatteryInfo = showBatteryInfo; mPluggedIn = pluggedIn; mBatteryLevel = batteryLevel; - updateStatusLines(true); + final MutableInt tmpIcon = new MutableInt(0); + update(BATTERY_INFO, getAltTextMessage(tmpIcon)); } public void onTimeChanged() { @@ -579,15 +589,17 @@ class KeyguardStatusViewManager implements OnClickListener { } public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { - setCarrierText(LockPatternUtils.getCarrierString(plmn, spn)); + mPlmn = plmn; + mSpn = spn; + updateCarrierTextWithSimStatus(mSimState); } public void onRingerModeChanged(int state) { } - public void onPhoneStateChanged(String newState) { - updateEmergencyCallButtonState(); + public void onPhoneStateChanged(int phoneState) { + updateEmergencyCallButtonState(phoneState); } /** {@inheritDoc} */ @@ -599,7 +611,7 @@ class KeyguardStatusViewManager implements OnClickListener { private SimStateCallback mSimStateCallback = new SimStateCallback() { public void onSimStateChanged(State simState) { - updateWithSimStatus(simState); + updateCarrierTextWithSimStatus(simState); } }; @@ -609,8 +621,21 @@ class KeyguardStatusViewManager implements OnClickListener { } } - public void hideEmergencyCallButton() { - mHideEmergencyCallButton = true; + /** + * Performs concentenation of PLMN/SPN + * @param plmn + * @param spn + * @return + */ + private static CharSequence makeCarierString(CharSequence plmn, CharSequence spn) { + if (plmn != null && spn == null) { + return plmn; + } else if (plmn != null && spn != null) { + return plmn + "|" + spn; + } else if (plmn == null && spn != null) { + return spn; + } else { + return ""; + } } - } diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java index 958f555ff567..10cf3aaf5c0f 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -88,6 +88,8 @@ public class KeyguardUpdateMonitor { private ArrayList<InfoCallback> mInfoCallbacks = Lists.newArrayList(); private ArrayList<SimStateCallback> mSimStateCallbacks = Lists.newArrayList(); private ContentObserver mContentObserver; + private int mRingMode; + private int mPhoneState; // messages for the handler private static final int MSG_TIME_UPDATE = 301; @@ -271,13 +273,21 @@ public class KeyguardUpdateMonitor { protected void handlePhoneStateChanged(String newState) { if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")"); + if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) { + mPhoneState = TelephonyManager.CALL_STATE_IDLE; + } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) { + mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK; + } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) { + mPhoneState = TelephonyManager.CALL_STATE_RINGING; + } for (int i = 0; i < mInfoCallbacks.size(); i++) { - mInfoCallbacks.get(i).onPhoneStateChanged(newState); + mInfoCallbacks.get(i).onPhoneStateChanged(mPhoneState); } } protected void handleRingerModeChange(int mode) { if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")"); + mRingMode = mode; for (int i = 0; i < mInfoCallbacks.size(); i++) { mInfoCallbacks.get(i).onRingerModeChanged(mode); } @@ -459,7 +469,7 @@ public class KeyguardUpdateMonitor { * {@link TelephonyManager@EXTRA_STATE_RINGING} * {@link TelephonyManager#EXTRA_STATE_OFFHOOK */ - void onPhoneStateChanged(String newState); + void onPhoneStateChanged(int phoneState); /** * Called when visibility of lockscreen clock changes, such as when @@ -484,6 +494,13 @@ public class KeyguardUpdateMonitor { public void registerInfoCallback(InfoCallback callback) { if (!mInfoCallbacks.contains(callback)) { mInfoCallbacks.add(callback); + // Notify listener of the current state + callback.onRefreshBatteryInfo(shouldShowBatteryInfo(), isPluggedIn(mBatteryStatus), + mBatteryLevel); + callback.onTimeChanged(); + callback.onRingerModeChanged(mRingMode); + callback.onPhoneStateChanged(mPhoneState); + callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn); } else { if (DEBUG) Log.e(TAG, "Object tried to add another INFO callback", new Exception("Whoops")); @@ -497,6 +514,8 @@ public class KeyguardUpdateMonitor { public void registerSimStateCallback(SimStateCallback callback) { if (!mSimStateCallbacks.contains(callback)) { mSimStateCallbacks.add(callback); + // Notify listener of the current state + callback.onSimStateChanged(mSimState); } else { if (DEBUG) Log.e(TAG, "Object tried to add another SIM callback", new Exception("Whoops")); @@ -574,4 +593,7 @@ public class KeyguardUpdateMonitor { return mClockVisible; } + public int getPhoneState() { + return mPhoneState; + } } diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java index 2fcf1dc3ebc2..59b546ddecfe 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java @@ -99,6 +99,11 @@ public abstract class KeyguardViewBase extends FrameLayout { abstract public void onScreenTurnedOn(); /** + * Called when the view needs to be shown. + */ + abstract public void show(); + + /** * Called when a key has woken the device to give us a chance to adjust our * state according the the key. We are responsible for waking the device * (by poking the wake lock) once we are ready. @@ -127,15 +132,6 @@ public abstract class KeyguardViewBase extends FrameLayout { */ abstract public void cleanUp(); - /** - * These were added to support FaceLock because the KeyguardViewManager needs to tell the - * LockPatternKeyguardView when to bind and and unbind with FaceLock service. Although - * implemented in LockPatternKeyguardView, these are not implemented in anything else - * derived from KeyguardViewBase - */ - abstract public void bindToFaceLock(); - abstract public void stopAndUnbindFromFaceLock(); - @Override public boolean dispatchKeyEvent(KeyEvent event) { if (shouldEventKeepScreenOnWhileKeyguardShowing(event)) { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index 91f152724b54..90972da1b591 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -167,7 +167,7 @@ public class KeyguardViewManager implements KeyguardWindowController { mKeyguardHost.addView(mKeyguardView, lp); if (mScreenOn) { - mKeyguardView.onScreenTurnedOn(); + mKeyguardView.show(); } } @@ -205,9 +205,6 @@ public class KeyguardViewManager implements KeyguardWindowController { mScreenOn = false; if (mKeyguardView != null) { mKeyguardView.onScreenTurnedOff(); - - // When screen is turned off, need to unbind from FaceLock service if using FaceLock - mKeyguardView.stopAndUnbindFromFaceLock(); } } @@ -218,9 +215,6 @@ public class KeyguardViewManager implements KeyguardWindowController { if (mKeyguardView != null) { mKeyguardView.onScreenTurnedOn(); - // When screen is turned on, need to bind to FaceLock service if we are using FaceLock - mKeyguardView.bindToFaceLock(); - // Caller should wait for this window to be shown before turning // on the screen. if (mKeyguardHost.getVisibility() == View.VISIBLE) { @@ -277,12 +271,6 @@ public class KeyguardViewManager implements KeyguardWindowController { public synchronized void hide() { if (DEBUG) Log.d(TAG, "hide()"); - if (mKeyguardView != null) { - // When view is hidden, need to unbind from FaceLock service if we are using FaceLock - // e.g., when device becomes unlocked - mKeyguardView.stopAndUnbindFromFaceLock(); - } - if (mKeyguardHost != null) { mKeyguardHost.setVisibility(View.GONE); // Don't do this right away, so we can let the view continue to animate diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 5d3dee9d1b0c..886997c43ac8 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -31,9 +31,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; -import android.media.Ringtone; -import android.media.RingtoneManager; -import android.net.Uri; +import android.media.SoundPool; import android.os.Handler; import android.os.LocalPowerManager; import android.os.Message; @@ -253,6 +251,11 @@ public class KeyguardViewMediator implements KeyguardViewCallback, private boolean mWaitingUntilKeyguardVisible = false; private LockPatternUtils mLockPatternUtils; + private SoundPool mLockSounds; + private int mLockSoundId; + private int mUnlockSoundId; + private int mLockSoundStreamId; + public KeyguardViewMediator(Context context, PhoneWindowManager callback, LocalPowerManager powerManager) { mContext = context; @@ -298,6 +301,22 @@ public class KeyguardViewMediator implements KeyguardViewCallback, final ContentResolver cr = mContext.getContentResolver(); mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1); + + mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0); + String soundPath = Settings.System.getString(cr, Settings.System.LOCK_SOUND); + if (soundPath != null) { + mLockSoundId = mLockSounds.load(soundPath, 1); + } + if (soundPath == null || mLockSoundId == 0) { + if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath); + } + soundPath = Settings.System.getString(cr, Settings.System.UNLOCK_SOUND); + if (soundPath != null) { + mUnlockSoundId = mLockSounds.load(soundPath, 1); + } + if (soundPath == null || mUnlockSoundId == 0) { + if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath); + } } /** @@ -766,7 +785,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, // Don't play lockscreen SFX if the screen went off due to // timeout. mSuppressNextLockSound = true; - + doKeyguardLocked(); } } @@ -777,7 +796,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState) // call ending && !mScreenOn // screen off && mExternallyEnabled) { // not disabled by any app - + // note: this is a way to gracefully reenable the keyguard when the call // ends and the screen is off without always reenabling the keyguard // each time the screen turns off while in call (and having an occasional ugly @@ -1044,28 +1063,11 @@ public class KeyguardViewMediator implements KeyguardViewCallback, final ContentResolver cr = mContext.getContentResolver(); if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) { - final String whichSound = locked - ? Settings.System.LOCK_SOUND - : Settings.System.UNLOCK_SOUND; - final String soundPath = Settings.System.getString(cr, whichSound); - if (soundPath != null) { - final Uri soundUri = Uri.parse("file://" + soundPath); - if (soundUri != null) { - final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); - if (sfx != null) { - sfx.setStreamType(AudioManager.STREAM_SYSTEM); - sfx.play(); - } else { - if (DEBUG) Log.d(TAG, "playSounds: failed to load ringtone from uri: " - + soundUri); - } - } else { - if (DEBUG) Log.d(TAG, "playSounds: could not parse Uri: " + soundPath); - } - } else { - if (DEBUG) Log.d(TAG, "playSounds: whichSound = " + whichSound - + "; soundPath was null"); - } + final int whichSound = locked + ? mLockSoundId + : mUnlockSoundId; + mLockSounds.stop(mLockSoundStreamId); + mLockSoundStreamId = mLockSounds.play(whichSound, 1.0f, 1.0f, 1, 0, 1.0f); } } @@ -1269,7 +1271,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, } /** {@inheritDoc} */ - public void onPhoneStateChanged(String newState) { + public void onPhoneStateChanged(int phoneState) { // ignored } diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 465fc2cb8814..f970ff3787be 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -114,6 +114,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0; private final int MSG_HIDE_FACELOCK_AREA_VIEW = 1; + // Long enough to stay black while dialer comes up + // Short enough to not be black if the user goes back immediately + private final int FACELOCK_VIEW_AREA_EMERGENCY_HIDE_TIMEOUT = 1000; + /** * The current {@link KeyguardScreen} will use this to communicate back to us. */ @@ -311,6 +315,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } public void takeEmergencyCallAction() { + // FaceLock must be stopped if it is running when emergency call is pressed + stopAndUnbindFromFaceLock(); + + // Delay hiding FaceLock area so unlock doesn't display while dialer is coming up + mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, + FACELOCK_VIEW_AREA_EMERGENCY_HIDE_TIMEOUT); + pokeWakelock(EMERGENCY_CALL_TIMEOUT); if (TelephonyManager.getDefault().getCallState() == TelephonyManager.CALL_STATE_OFFHOOK) { @@ -493,16 +504,38 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } else { ((KeyguardScreen) mUnlockScreen).onPause(); } + + // When screen is turned off, need to unbind from FaceLock service if using FaceLock + stopAndUnbindFromFaceLock(); } @Override public void onScreenTurnedOn() { mScreenOn = true; + show(); + + // When screen is turned on, need to bind to FaceLock service if we are using FaceLock + // But only if not dealing with a call + if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE) { + bindToFaceLock(); + } else { + mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + } + } + + @Override + public void show() { if (mMode == Mode.LockScreen) { ((KeyguardScreen) mLockScreen).onResume(); } else { ((KeyguardScreen) mUnlockScreen).onResume(); } + + if (mLockPatternUtils.usingBiometricWeak()) { + mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); + } else { + mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + } } private void recreateLockScreen() { @@ -532,6 +565,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler @Override protected void onDetachedFromWindow() { removeCallbacks(mRecreateRunnable); + + // When view is hidden, need to unbind from FaceLock service if we are using FaceLock + // e.g., when device becomes unlocked + stopAndUnbindFromFaceLock(); + super.onDetachedFromWindow(); } @@ -540,7 +578,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen); mConfiguration = newConfig; if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed"); - updateScreen(mMode, true /* force */); + removeCallbacks(mRecreateRunnable); + post(mRecreateRunnable); } @Override @@ -940,18 +979,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // Everything below pertains to FaceLock - might want to separate this out // Only pattern and pin unlock screens actually have a view for the FaceLock area, so it's not - // uncommon for it to not exist. But if it does exist, we need to make sure it's showing if - // FaceLock is enabled, and make sure it's not showing if FaceLock is disabled + // uncommon for it to not exist. But if it does exist, we need to make sure it's shown (hiding + // the fallback) if FaceLock is enabled, and make sure it's hidden (showing the unlock) if + // FaceLock is disabled private void initializeFaceLockAreaView(View view) { mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView); if (mFaceLockAreaView == null) { if (DEBUG) Log.d(TAG, "Layout does not have faceLockAreaView"); - } else { - if (mLockPatternUtils.usingBiometricWeak()) { - mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); - } else { - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); - } } } @@ -962,10 +996,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_SHOW_FACELOCK_AREA_VIEW: - mFaceLockAreaView.setVisibility(View.VISIBLE); + if (mFaceLockAreaView != null) { + mFaceLockAreaView.setVisibility(View.VISIBLE); + } break; case MSG_HIDE_FACELOCK_AREA_VIEW: - mFaceLockAreaView.setVisibility(View.GONE); + if (mFaceLockAreaView != null) { + mFaceLockAreaView.setVisibility(View.GONE); + } break; default: Log.w(TAG, "Unhandled message"); @@ -985,9 +1023,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler if (DEBUG) Log.d(TAG, "after bind to FaceLock service"); mBoundToFaceLockService = true; } else { - // On startup I've seen onScreenTurnedOn() get called twice without - // onScreenTurnedOff() being called in between, which can cause this (bcolonna) - if (DEBUG) Log.w(TAG, "Attempt to bind to FaceLock when already bound"); + Log.w(TAG, "Attempt to bind to FaceLock when already bound"); } } } @@ -1005,7 +1041,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } else { // This could probably happen after the session when someone activates FaceLock // because it wasn't active when the phone was turned on - if (DEBUG) Log.w(TAG, "Attempt to unbind from FaceLock when not bound"); + Log.w(TAG, "Attempt to unbind from FaceLock when not bound"); } } } @@ -1036,7 +1072,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mFaceLockService = null; mFaceLockServiceRunning = false; } - if (DEBUG) Log.w(TAG, "Unexpected disconnect from FaceLock service"); + Log.w(TAG, "Unexpected disconnect from FaceLock service"); } }; @@ -1087,36 +1123,21 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // Stops the FaceLock UI and indicates that the phone should be unlocked @Override public void unlock() { - if (DEBUG) Log.d(TAG, "FaceLock unlock"); - // Note that we don't hide the client FaceLockAreaView because we want to keep the - // lock screen covered while the phone is unlocked - + if (DEBUG) Log.d(TAG, "FaceLock unlock()"); + mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); // Keep fallback covered stopFaceLock(); + mKeyguardScreenCallback.keyguardDone(true); mKeyguardScreenCallback.reportSuccessfulUnlockAttempt(); } // Stops the FaceLock UI and exposes the backup method without unlocking + // This means either the user has cancelled out or FaceLock failed to recognize them @Override public void cancel() { - // In this case, either the user has cancelled out, or FaceLock failed to recognize them - if (DEBUG) Log.d(TAG, "FaceLock cancel"); - // Here we hide the client FaceLockViewArea to expose the underlying backup method - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); - stopFaceLock(); - } - - // Stops the FaceLock UI and puts the phone to sleep - @Override - public void sleepDevice() { - // In this case, it appears the phone has been turned on accidentally - if (DEBUG) Log.d(TAG, "FaceLock accidental turn on"); - // Here we hide the client FaceLockViewArea to expose the underlying backup method - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + if (DEBUG) Log.d(TAG, "FaceLock cancel()"); + mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); // Expose fallback stopFaceLock(); - // TODO(bcolonna): how do we put the phone back to sleep (i.e., turn off the screen) - // TODO(bcolonna): this should be removed once the service is no longer calling it - // because we are just going to let the lockscreen timeout } }; } diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 4f6df3659f67..3469483330d6 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -336,10 +336,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen { } mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils, - mCallback); - - // LockScreen doesn't show the emergency call button by default - mStatusViewManager.hideEmergencyCallButton(); + mCallback, false); setFocusable(true); setFocusableInTouchMode(true); diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java index 2f2d3b7c635d..6d2f2f29fc05 100644 --- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java @@ -98,7 +98,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen } mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils, - mCallback); + mCallback, true); final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality(); mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java index 88c42a6367dd..9a6d2cc67f46 100644 --- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java @@ -171,7 +171,7 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient } mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, - mLockPatternUtils, mCallback); + mLockPatternUtils, mCallback, true); mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 1b7271db843b..9205b9ac2d15 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -43,6 +43,7 @@ import android.app.KeyguardManager; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.PixelFormat; @@ -63,6 +64,7 @@ import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.ActionMode; +import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.IRotationWatcher; import android.view.IWindowManager; @@ -990,7 +992,23 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { * @return Whether the initialization was successful. */ protected boolean initializePanelMenu(final PanelFeatureState st) { - final MenuBuilder menu = new MenuBuilder(getContext()); + Context context = getContext(); + + // If we have an action bar, initialize the menu with a context themed for it. + if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR) && + mActionBar != null) { + TypedValue outValue = new TypedValue(); + Resources.Theme currentTheme = context.getTheme(); + currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme, + outValue, true); + final int targetThemeRes = outValue.resourceId; + + if (targetThemeRes != 0 && context.getThemeResId() != targetThemeRes) { + context = new ContextThemeWrapper(context, targetThemeRes); + } + } + + final MenuBuilder menu = new MenuBuilder(context); menu.setCallback(this); st.setMenu(menu); @@ -2135,6 +2153,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { com.android.internal.R.attr.actionModePopupWindowStyle); mActionModePopup.setLayoutInScreenEnabled(true); mActionModePopup.setLayoutInsetDecor(true); + mActionModePopup.setFocusable(true); + mActionModePopup.setOutsideTouchable(false); + mActionModePopup.setTouchModal(false); mActionModePopup.setWindowLayoutType( WindowManager.LayoutParams.TYPE_APPLICATION); mActionModePopup.setContentView(mActionModeView); @@ -2731,6 +2752,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } else { mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar); if (mActionBar != null) { + mActionBar.setWindowCallback(getCallback()); if (mActionBar.getTitle() == null) { mActionBar.setWindowTitle(mTitle); } @@ -2743,28 +2765,30 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } boolean splitActionBar = false; - if ((mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0) { + final boolean splitWhenNarrow = + (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0; + if (splitWhenNarrow) { splitActionBar = getContext().getResources().getBoolean( com.android.internal.R.bool.split_action_bar_is_narrow); } else { splitActionBar = getWindowStyle().getBoolean( com.android.internal.R.styleable.Window_windowSplitActionBar, false); } - if (splitActionBar) { - final ActionBarContainer splitView = (ActionBarContainer) findViewById( - com.android.internal.R.id.split_action_bar); - if (splitView != null) { - splitView.setVisibility(View.VISIBLE); - mActionBar.setSplitActionBar(splitActionBar); - mActionBar.setSplitView(splitView); - - final ActionBarContextView cab = (ActionBarContextView) findViewById( - com.android.internal.R.id.action_context_bar); - cab.setSplitView(splitView); - } else { - Log.e(TAG, "Requested split action bar with " + - "incompatible window decor! Ignoring request."); - } + final ActionBarContainer splitView = (ActionBarContainer) findViewById( + com.android.internal.R.id.split_action_bar); + if (splitView != null) { + mActionBar.setSplitView(splitView); + mActionBar.setSplitActionBar(splitActionBar); + mActionBar.setSplitWhenNarrow(splitWhenNarrow); + + final ActionBarContextView cab = (ActionBarContextView) findViewById( + com.android.internal.R.id.action_context_bar); + cab.setSplitView(splitView); + cab.setSplitActionBar(splitActionBar); + cab.setSplitWhenNarrow(splitWhenNarrow); + } else if (splitActionBar) { + Log.e(TAG, "Requested split action bar with " + + "incompatible window decor! Ignoring request."); } // Post the panel invalidate for later; avoid application onCreateOptionsMenu @@ -3470,6 +3494,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } public boolean onOpenSubMenu(MenuBuilder subMenu) { + if (subMenu == null) return false; + // Set a simple callback for the submenu subMenu.setCallback(this); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index c8c0041b2f95..968180ccf06d 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -280,7 +280,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; int mUserRotation = Surface.ROTATION_0; - boolean mAllowAllRotations; + int mAllowAllRotations = -1; boolean mCarDockEnablesAccelerometer; boolean mDeskDockEnablesAccelerometer; int mLidKeyboardAccessibility; @@ -385,9 +385,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mPortraitRotation = 0; // default portrait rotation int mUpsideDownRotation = 0; // "other" portrait rotation - // Nothing to see here, move along... - int mFancyRotationAnimation; - // What we do when the user long presses on home private int mLongPressOnHomeBehavior = -1; @@ -439,12 +436,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void onChange(boolean selfChange) { updateSettings(); - try { - mWindowManager.setRotation(USE_LAST_ROTATION, false, - mFancyRotationAnimation); - } catch (RemoteException e) { - // Ignore - } + updateRotation(false); } } @@ -454,48 +446,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - public void onOrientationChanged(int rotation) { - // Send updates based on orientation value - if (localLOGV) Log.v(TAG, "onOrientationChanged, rotation changed to " +rotation); - try { - mWindowManager.setRotation(rotation, false, - mFancyRotationAnimation); - } catch (RemoteException e) { - // Ignore - - } - } + public void onProposedRotationChanged(int rotation) { + if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation); + updateRotation(false); + } } MyOrientationListener mOrientationListener; - boolean useSensorForOrientationLp(int appOrientation) { - // The app says use the sensor. - if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { - return true; - } - // The user preference says we can rotate, and the app is willing to rotate. - if (mAccelerometerDefault != 0 && - (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) { - return true; - } - // We're in a dock that has a rotation affinity, and the app is willing to rotate. - if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) - || (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) { - // Note we override the nosensor flag here. - if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { - return true; - } - } - // Else, don't use the sensor. - return false; - } - /* * We always let the sensor be switched on by default except when * the user has explicitly disabled sensor based rotation or when the @@ -696,6 +653,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager); mHandler = new Handler(); mOrientationListener = new MyOrientationListener(mContext); + try { + mOrientationListener.setCurrentRotation(windowManager.getRotation()); + } catch (RemoteException ex) { } SettingsObserver settingsObserver = new SettingsObserver(mHandler); settingsObserver.observe(); mShortcutManager = new ShortcutManager(context, mHandler); @@ -723,8 +683,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.integer.config_carDockRotation); mDeskDockRotation = readRotation( com.android.internal.R.integer.config_deskDockRotation); - mAllowAllRotations = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_allowAllRotations); mCarDockEnablesAccelerometer = mContext.getResources().getBoolean( com.android.internal.R.bool.config_carDockEnablesAccelerometer); mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean( @@ -760,6 +718,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Controls rotation and the like. initializeHdmiState(); + + // Match current screen state. + if (mPowerManager.isScreenOn()) { + screenTurningOn(null); + } else { + screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER); + } } public void setInitialDisplaySize(int width, int height) { @@ -826,8 +791,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mIncallPowerBehavior = Settings.Secure.getInt(resolver, Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT); - mFancyRotationAnimation = Settings.System.getInt(resolver, - "fancy_rotation_anim", 0) != 0 ? 0x80 : 0; int accelerometerDefault = Settings.System.getInt(resolver, Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION); @@ -882,7 +845,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateScreenSaverTimeoutLocked(); } if (updateRotation) { - updateRotation(0); + updateRotation(true); } if (addView != null) { WindowManager.LayoutParams lp = new WindowManager.LayoutParams( @@ -1025,8 +988,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void adjustConfigurationLw(Configuration config) { readLidState(); - - mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN); + updateKeyboardVisibility(); if (config.keyboard == Configuration.KEYBOARD_NOKEYS) { config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES; @@ -2295,8 +2257,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { // lid changed state mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED; + updateKeyboardVisibility(); + boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen); - updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateRotation(true); if (awakeNow) { // If the lid is opening and we don't have to keep the // keyguard up, then we can turn on the screen @@ -2325,7 +2289,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { void setHdmiPlugged(boolean plugged) { if (mHdmiPlugged != plugged) { mHdmiPlugged = plugged; - updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateRotation(true); Intent intent = new Intent(ACTION_HDMI_PLUGGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); @@ -2802,7 +2766,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } catch (RemoteException e) { } } - updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateRotation(true); updateOrientationListenerLp(); } }; @@ -2825,31 +2789,42 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void screenTurningOn(final ScreenOnListener screenOnListener) { EventLog.writeEvent(70000, 1); - //Slog.i(TAG, "Screen turning on..."); - mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() { - @Override public void onShown(IBinder windowToken) { - if (windowToken != null) { - try { - mWindowManager.waitForWindowDrawn(windowToken, new IRemoteCallback.Stub() { - @Override public void sendResult(Bundle data) { - Slog.i(TAG, "Lock screen displayed!"); - screenOnListener.onScreenOn(); - synchronized (mLock) { - mScreenOnFully = true; + if (false) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Screen turning on...", here); + } + if (screenOnListener != null) { + mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() { + @Override public void onShown(IBinder windowToken) { + if (windowToken != null) { + try { + mWindowManager.waitForWindowDrawn(windowToken, + new IRemoteCallback.Stub() { + @Override public void sendResult(Bundle data) { + Slog.i(TAG, "Lock screen displayed!"); + screenOnListener.onScreenOn(); + synchronized (mLock) { + mScreenOnFully = true; + } } - } - }); - } catch (RemoteException e) { - } - } else { - Slog.i(TAG, "No lock screen!"); - screenOnListener.onScreenOn(); - synchronized (mLock) { - mScreenOnFully = true; + }); + } catch (RemoteException e) { + } + } else { + Slog.i(TAG, "No lock screen!"); + screenOnListener.onScreenOn(); + synchronized (mLock) { + mScreenOnFully = true; + } } } + }); + } else { + synchronized (mLock) { + mScreenOnFully = true; } - }); + } synchronized (mLock) { mScreenOnEarly = true; updateOrientationListenerLp(); @@ -2898,6 +2873,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { return mKeyguardMediator.isInputRestricted(); } + public void dismissKeyguardLw() { + if (!mKeyguardMediator.isSecure()) { + if (mKeyguardMediator.isShowing()) { + mHandler.post(new Runnable() { + public void run() { + mKeyguardMediator.keyguardDone(false, true); + } + }); + } + } + } + void sendCloseSystemWindows() { sendCloseSystemWindows(mContext, null); } @@ -2914,10 +2901,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - - public int rotationForOrientationLw(int orientation, int lastRotation, - boolean displayEnabled) { + @Override + public int rotationForOrientationLw(int orientation, int lastRotation) { if (false) { Slog.v(TAG, "rotationForOrientationLw(orient=" + orientation + ", last=" + lastRotation @@ -2928,128 +2914,142 @@ public class PhoneWindowManager implements WindowManagerPolicy { } synchronized (mLock) { + int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 + if (sensorRotation < 0) { + sensorRotation = lastRotation; + } + + int preferredRotation = -1; + if (mHdmiPlugged) { + // Ignore sensor when plugged into HDMI. + preferredRotation = mLandscapeRotation; + } else if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) { + // Ignore sensor when lid switch is open and rotation is forced. + preferredRotation = mLidOpenRotation; + } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR + && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { + // Ignore sensor when in car dock unless explicitly enabled. + // This case can override the behavior of NOSENSOR, and can also + // enable 180 degree rotation while docked. + preferredRotation = mCarDockEnablesAccelerometer + ? sensorRotation : mCarDockRotation; + } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK + && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { + // Ignore sensor when in desk dock unless explicitly enabled. + // This case can override the behavior of NOSENSOR, and can also + // enable 180 degree rotation while docked. + preferredRotation = mDeskDockEnablesAccelerometer + ? sensorRotation : mDeskDockRotation; + } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { + // Ignore sensor when user locked rotation. + preferredRotation = mUserRotation; + } else if ((mAccelerometerDefault != 0 + && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER + || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) + || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR + || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR + || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE + || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { + // Otherwise, use sensor only if requested by the application or enabled + // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. + if (mAllowAllRotations < 0) { + // Can't read this during init() because the context doesn't + // have display metrics at that time so we cannot determine + // tablet vs. phone then. + mAllowAllRotations = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; + } + if (sensorRotation != Surface.ROTATION_180 + || mAllowAllRotations == 1 + || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) { + preferredRotation = sensorRotation; + } else { + preferredRotation = lastRotation; + } + } + + // TODO: Sometimes, we might want to override the application-requested + // orientation, such as when HDMI is plugged in or when docked. + // We can do that by modifying the appropriate cases above to return + // the preferred orientation directly instead of continuing on down here. + switch (orientation) { case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: - //always return portrait if orientation set to portrait + // Always return portrait if orientation set to portrait. return mPortraitRotation; + case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: - //always return landscape if orientation set to landscape + // Always return landscape if orientation set to landscape. return mLandscapeRotation; + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: - //always return portrait if orientation set to portrait + // Always return portrait if orientation set to portrait. return mUpsideDownRotation; + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: - //always return seascape if orientation set to reverse landscape + // Always return seascape if orientation set to reverse landscape. return mSeascapeRotation; + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: - //return either landscape rotation based on the sensor - return getCurrentLandscapeRotation(lastRotation); - case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: - return getCurrentPortraitRotation(lastRotation); - } + // Return either landscape rotation. + if (isLandscapeOrSeascape(preferredRotation)) { + return preferredRotation; + } + if (isLandscapeOrSeascape(lastRotation)) { + return lastRotation; + } + return mLandscapeRotation; - // case for nosensor meaning ignore sensor and consider only lid - // or orientation sensor disabled - //or case.unspecified - if (mHdmiPlugged) { - return mLandscapeRotation; - } else if (mLidOpen == LID_OPEN) { - return mLidOpenRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) { - return mCarDockRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { - return mDeskDockRotation; - } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - return mUserRotation; - } else { - if (useSensorForOrientationLp(orientation)) { - // Disable 180 degree rotation unless allowed by default for the device - // or explicitly requested by the application. - int rotation = mOrientationListener.getCurrentRotation(lastRotation); - if (rotation == Surface.ROTATION_180 - && !mAllowAllRotations - && orientation != ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) { + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: + // Return either portrait rotation. + if (isAnyPortrait(preferredRotation)) { + return preferredRotation; + } + if (isAnyPortrait(lastRotation)) { return lastRotation; } - return rotation; - } - return Surface.ROTATION_0; - } - } - } + return mPortraitRotation; - public int getLockedRotationLw() { - synchronized (mLock) { - if (false) { - // Not yet working. - if (mHdmiPlugged) { + default: + // For USER, UNSPECIFIED and NOSENSOR, just return the preferred + // orientation we already calculated. + if (preferredRotation >= 0) { + return preferredRotation; + } return Surface.ROTATION_0; - } else if (mLidOpen == LID_OPEN) { - return mLidOpenRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) { - return mCarDockRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { - return mDeskDockRotation; - } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - return mUserRotation; - } } - return -1; } } - private int getCurrentLandscapeRotation(int lastRotation) { - // if the user has locked rotation, we ignore the sensor - if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - if (isLandscapeOrSeascape(mUserRotation)) { - return mUserRotation; - } else { - // it seems odd to obey the sensor at all if rotation lock is enabled - return mLandscapeRotation; - } - } + @Override + public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { + switch (orientation) { + case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: + return isAnyPortrait(rotation); + + case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: + return isLandscapeOrSeascape(rotation); - int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation); - if (isLandscapeOrSeascape(sensorRotation)) { - return sensorRotation; - } - // try to preserve the old rotation if it was landscape - if (isLandscapeOrSeascape(lastRotation)) { - return lastRotation; + default: + return true; } - // default to one of the primary landscape rotation - return mLandscapeRotation; } - private boolean isLandscapeOrSeascape(int sensorRotation) { - return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation; + @Override + public void setRotationLw(int rotation) { + mOrientationListener.setCurrentRotation(rotation); } - private int getCurrentPortraitRotation(int lastRotation) { - // if the user has locked rotation, we ignore the sensor - if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - if (isAnyPortrait(mUserRotation)) { - return mUserRotation; - } else { - // it seems odd to obey the sensor at all if rotation lock is enabled - return mPortraitRotation; - } - } - - int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation); - if (isAnyPortrait(sensorRotation)) { - return sensorRotation; - } - // try to preserve the old rotation if it was portrait - if (isAnyPortrait(lastRotation)) { - return lastRotation; - } - // default to one of the primary portrait rotations - return mPortraitRotation; + private boolean isLandscapeOrSeascape(int rotation) { + return rotation == mLandscapeRotation || rotation == mSeascapeRotation; } - private boolean isAnyPortrait(int sensorRotation) { - return sensorRotation == mPortraitRotation || sensorRotation == mUpsideDownRotation; + private boolean isAnyPortrait(int rotation) { + return rotation == mPortraitRotation || rotation == mUpsideDownRotation; } @@ -3298,26 +3298,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void enableScreenAfterBoot() { readLidState(); - updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateKeyboardVisibility(); + + updateRotation(true); } - void updateRotation(int animFlags) { + private void updateKeyboardVisibility() { mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN); - int rotation = Surface.ROTATION_0; - if (mHdmiPlugged) { - rotation = Surface.ROTATION_0; - } else if (mLidOpen == LID_OPEN) { - rotation = mLidOpenRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) { - rotation = mCarDockRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { - rotation = mDeskDockRotation; - } - //if lid is closed orientation will be portrait + } + + void updateRotation(boolean alwaysSendConfiguration) { try { //set orientation on WindowManager - mWindowManager.setRotation(rotation, true, - mFancyRotationAnimation | animFlags); + mWindowManager.updateRotation(alwaysSendConfiguration); } catch (RemoteException e) { // Ignore } diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java index 520d3021476d..6acd1c5898a8 100644 --- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java @@ -27,6 +27,7 @@ import com.android.internal.telephony.ITelephony; import com.android.internal.widget.LockPatternUtils; import android.text.Editable; +import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; @@ -40,21 +41,20 @@ import com.android.internal.R; * Displays a dialer like interface to unlock the SIM PUK. */ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, - View.OnClickListener { + View.OnClickListener, View.OnFocusChangeListener { private static final int DIGIT_PRESS_WAKE_MILLIS = 5000; private final KeyguardUpdateMonitor mUpdateMonitor; private final KeyguardScreenCallback mCallback; + private KeyguardStatusViewManager mKeyguardStatusViewManager; private TextView mHeaderText; private TextView mPukText; private TextView mPinText; - private TextView mFocusedEntry; - private TextView mOkButton; - + private View mOkButton; private View mDelPukButton; private View mDelPinButton; @@ -66,8 +66,6 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, private int mKeyboardHidden; - private KeyguardStatusViewManager mKeyguardStatusViewManager; - private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; public SimPukUnlockScreen(Context context, Configuration configuration, @@ -92,44 +90,33 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, } mHeaderText = (TextView) findViewById(R.id.headerText); + mPukText = (TextView) findViewById(R.id.pukDisplay); - mPukText.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - requestFocus(mPukText); - mCallback.pokeWakelock(); - } - }); mPinText = (TextView) findViewById(R.id.pinDisplay); - mPinText.setOnClickListener(this); - mDelPukButton = findViewById(R.id.pukDel); - mDelPukButton.setOnClickListener(this); mDelPinButton = findViewById(R.id.pinDel); - mDelPinButton.setOnClickListener(this); + mOkButton = findViewById(R.id.ok); - mOkButton = (TextView) findViewById(R.id.ok); - - mHeaderText.setText(R.string.keyguard_password_enter_puk_code); - mPukText.setFocusable(false); - mPinText.setFocusable(false); + mDelPinButton.setOnClickListener(this); + mDelPukButton.setOnClickListener(this); mOkButton.setOnClickListener(this); - requestFocus(mPukText); + mHeaderText.setText(R.string.keyguard_password_enter_puk_code); + // To make marquee work + mHeaderText.setSelected(true); mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor, - lockpatternutils, callback); + lockpatternutils, callback, true); - setFocusableInTouchMode(true); - } - - private void requestFocus(TextView entry) { - mFocusedEntry = entry; - mFocusedEntry.setText(""); + mPinText.setFocusableInTouchMode(true); + mPinText.setOnFocusChangeListener(this); + mPukText.setFocusableInTouchMode(true); + mPukText.setOnFocusChangeListener(this); } /** {@inheritDoc} */ public boolean needsInput() { - return true; + return false; } /** {@inheritDoc} */ @@ -141,9 +128,6 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, public void onResume() { // start fresh mHeaderText.setText(R.string.keyguard_password_enter_puk_code); - requestFocus(mPukText); - mPinText.setText(""); - mKeyguardStatusViewManager.onResume(); } @@ -196,25 +180,32 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, public void onClick(View v) { if (v == mDelPukButton) { + if (mFocusedEntry != mPukText) + mPukText.requestFocus(); final Editable digits = mPukText.getEditableText(); final int len = digits.length(); if (len > 0) { digits.delete(len-1, len); } - mCallback.pokeWakelock(); } else if (v == mDelPinButton) { + if (mFocusedEntry != mPinText) + mPinText.requestFocus(); final Editable digits = mPinText.getEditableText(); final int len = digits.length(); if (len > 0) { digits.delete(len-1, len); } - mCallback.pokeWakelock(); - } else if (v == mPinText) { - requestFocus(mPinText); - mCallback.pokeWakelock(); } else if (v == mOkButton) { checkPuk(); } + mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS); + + } + + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) + mFocusedEntry = (TextView)v; } private Dialog getSimUnlockProgressDialog() { @@ -236,7 +227,6 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, // otherwise, display a message to the user, and don't submit. mHeaderText.setText(R.string.invalidPuk); mPukText.setText(""); - mCallback.pokeWakelock(); return; } @@ -245,7 +235,6 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, // otherwise, display a message to the user, and don't submit. mHeaderText.setText(R.string.invalidPin); mPinText.setText(""); - mCallback.pokeWakelock(); return; } @@ -267,7 +256,6 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, mPukText.setText(""); mPinText.setText(""); } - mCallback.pokeWakelock(); } }.start(); } @@ -290,7 +278,7 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, if (len > 0) { digits.delete(len-1, len); } - mCallback.pokeWakelock(); + mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS); return true; } diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java index 1acf68172241..184748abe83f 100644 --- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java @@ -100,7 +100,7 @@ public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, Vie mOkButton.setOnClickListener(this); mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor, - lockpatternutils, callback); + lockpatternutils, callback, true); setFocusableInTouchMode(true); } diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index a58f64c3a989..01f5a6f433be 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -985,6 +985,10 @@ AudioFlinger::ThreadBase::~ThreadBase() mNewParameters.clear(); // do not lock the mutex in destructor releaseWakeLock_l(); + if (mPowerManager != 0) { + sp<IBinder> binder = mPowerManager->asBinder(); + binder->unlinkToDeath(mDeathRecipient); + } } void AudioFlinger::ThreadBase::exit() @@ -7440,12 +7444,21 @@ void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend) } } + +// The volume effect is used for automated tests only +#ifndef OPENSL_ES_H_ +static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_; +#endif //OPENSL_ES_H_ + bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc) { // auxiliary effects and visualizer are never suspended on output mix if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) && (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) || - (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0))) { + (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) || + (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) { return false; } return true; diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp index 80ee28ee6ce2..790b395c7b41 100644 --- a/services/input/EventHub.cpp +++ b/services/input/EventHub.cpp @@ -639,6 +639,8 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz sizeof(struct input_event) * capacity); if (readSize == 0 || (readSize < 0 && errno == ENODEV)) { // Device was removed before INotify noticed. + LOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d capacity: %d errno: %d)\n", + device->fd, readSize, bufferSize, capacity, errno); deviceChanged = true; closeDeviceLocked(device); } else if (readSize < 0) { @@ -1254,6 +1256,7 @@ status_t EventHub::readNotifyLocked() { if(event->mask & IN_CREATE) { openDeviceLocked(devname); } else { + LOGI("Removing device '%s' due to inotify event\n", devname); closeDeviceByPathLocked(devname); } } diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index 5ffcdc50e800..b8c44d9cf99a 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -477,7 +477,7 @@ class AlarmManagerService extends IAlarmManager.Stub { : bs.filterStats.entrySet()) { pw.print(" "); pw.print(fe.getValue().count); pw.print(" alarms: "); - pw.println(fe.getKey().getIntent().toShortString(true, false)); + pw.println(fe.getKey().getIntent().toShortString(false, true, false)); } } } diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 6ac6c9807a46..fe49cd2bd4c8 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -3380,7 +3380,8 @@ class BackupManagerService extends IBackupManager.Stub { Uri packageUri = Uri.fromFile(apkFile); mInstallObserver.reset(); mPackageManager.installPackage(packageUri, mInstallObserver, - PackageManager.INSTALL_REPLACE_EXISTING, installerPackage); + PackageManager.INSTALL_REPLACE_EXISTING | PackageManager.INSTALL_FROM_ADB, + installerPackage); mInstallObserver.waitForCompletion(); if (mInstallObserver.getResult() != PackageManager.INSTALL_SUCCEEDED) { @@ -4373,8 +4374,13 @@ class BackupManagerService extends IBackupManager.Stub { ParcelFileDescriptor.MODE_TRUNCATE); if (mTransport.getRestoreData(mBackupData) != BackupConstants.TRANSPORT_OK) { + // Transport-level failure, so we wind everything up and + // terminate the restore operation. Slog.e(TAG, "Error getting restore data for " + packageName); EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE); + mBackupData.close(); + mBackupDataName.delete(); + executeNextState(RestoreState.FINAL); return; } @@ -5590,6 +5596,16 @@ class BackupManagerService extends IBackupManager.Stub { } private void dumpInternal(PrintWriter pw) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump Backup Manager service from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + + " without permission " + + android.Manifest.permission.DUMP); + return; + } + synchronized (mQueueLock) { pw.println("Backup Manager is " + (mEnabled ? "enabled" : "disabled") + " / " + (!mProvisioned ? "not " : "") + "provisioned / " diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 8b58d42bdd89..8112b1d0d149 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -35,6 +35,7 @@ import android.net.EthernetDataTracker; import android.net.IConnectivityManager; import android.net.INetworkPolicyListener; import android.net.INetworkPolicyManager; +import android.net.INetworkStatsService; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.LinkProperties.CompareResult; @@ -97,7 +98,7 @@ import java.util.List; public class ConnectivityService extends IConnectivityManager.Stub { private static final boolean DBG = true; - private static final boolean VDBG = true; + private static final boolean VDBG = false; private static final String TAG = "ConnectivityService"; private static final boolean LOGD_RULES = false; @@ -306,8 +307,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { // the set of network types that can only be enabled by system/sig apps List mProtectedNetworks; - public ConnectivityService( - Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) { + public ConnectivityService(Context context, INetworkManagementService netd, + INetworkStatsService statsService, INetworkPolicyManager policyManager) { if (DBG) log("ConnectivityService starting up"); HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread"); @@ -496,7 +497,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b); - mTethering = new Tethering(mContext, nmService, mHandler.getLooper()); + mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper()); mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 || mTethering.getTetherableWifiRegexs().length != 0 || mTethering.getTetherableBluetoothRegexs().length != 0) && @@ -867,7 +868,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { // javadoc from interface public int startUsingNetworkFeature(int networkType, String feature, IBinder binder) { - if (DBG) { + if (VDBG) { log("startUsingNetworkFeature for net " + networkType + ": " + feature); } enforceChangePermission(); @@ -933,17 +934,19 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (ni.isConnected() == true) { // add the pid-specific dns handleDnsConfigurationChange(usedNetworkType); - if (DBG) log("special network already active"); + if (VDBG) log("special network already active"); return Phone.APN_ALREADY_ACTIVE; } - if (DBG) log("special network already connecting"); + if (VDBG) log("special network already connecting"); return Phone.APN_REQUEST_STARTED; } // check if the radio in play can make another contact // assume if cannot for now - if (DBG) log("reconnecting to special network"); + if (DBG) { + log("startUsingNetworkFeature reconnecting to " + networkType + ": " + feature); + } network.reconnect(); return Phone.APN_REQUEST_STARTED; } else { @@ -985,7 +988,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { return stopUsingNetworkFeature(u, true); } else { // none found! - if (VDBG) log("ignoring stopUsingNetworkFeature - not a live request"); + if (VDBG) log("stopUsingNetworkFeature - not a live request, ignoring"); return 1; } } @@ -999,12 +1002,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { NetworkStateTracker tracker = null; boolean callTeardown = false; // used to carry our decision outside of sync block - if (DBG) { - log("stopUsingNetworkFeature for net " + networkType + - ": " + feature); + if (VDBG) { + log("stopUsingNetworkFeature: net " + networkType + ": " + feature); } if (!ConnectivityManager.isNetworkTypeValid(networkType)) { + if (DBG) { + log("stopUsingNetworkFeature: net " + networkType + ": " + feature + + ", net is invalid"); + } return -1; } @@ -1013,7 +1019,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { synchronized(this) { // check if this process still has an outstanding start request if (!mFeatureUsers.contains(u)) { - if (DBG) log("ignoring - this process has no outstanding requests"); + if (VDBG) { + log("stopUsingNetworkFeature: this process has no outstanding requests" + + ", ignoring"); + } return 1; } u.unlinkDeathRecipient(); @@ -1028,7 +1037,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (ignoreDups == false) { for (FeatureUser x : mFeatureUsers) { if (x.isSameUser(u)) { - if (DBG) log("ignoring stopUsingNetworkFeature as dup is found"); + if (VDBG) log("stopUsingNetworkFeature: dup is found, ignoring"); return 1; } } @@ -1039,7 +1048,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { tracker = mNetTrackers[usedNetworkType]; if (tracker == null) { - if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType); + if (DBG) { + log("stopUsingNetworkFeature: net " + networkType + ": " + feature + + " no known tracker for used net type " + usedNetworkType); + } return -1; } if (usedNetworkType != networkType) { @@ -1047,17 +1059,25 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetRequestersPids[usedNetworkType].remove(currentPid); reassessPidDns(pid, true); if (mNetRequestersPids[usedNetworkType].size() != 0) { - if (DBG) log("not tearing down special network - " + - "others still using it"); + if (VDBG) { + log("stopUsingNetworkFeature: net " + networkType + ": " + feature + + " others still using it"); + } return 1; } callTeardown = true; } else { - if (DBG) log("not a known feature - dropping"); + if (DBG) { + log("stopUsingNetworkFeature: net " + networkType + ": " + feature + + " not a known feature - dropping"); + } } } - if (DBG) log("Doing network teardown"); + if (callTeardown) { + if (DBG) { + log("stopUsingNetworkFeature: teardown net " + networkType + ": " + feature); + } tracker.teardown(); return 1; } else { @@ -1592,7 +1612,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { mInitialBroadcast = new Intent(intent); } intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - if (DBG) { + if (VDBG) { log("sendStickyBroadcast: action=" + intent.getAction()); } @@ -1604,7 +1624,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (delayMs <= 0) { sendStickyBroadcast(intent); } else { - if (DBG) { + if (VDBG) { log("sendStickyBroadcastDelayed: delayMs=" + delayMs + ", action=" + intent.getAction()); } @@ -1779,12 +1799,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } if (resetDns) { - if (DBG) log("resetting DNS cache for " + iface); + if (VDBG) log("resetting DNS cache for " + iface); try { mNetd.flushInterfaceDnsCache(iface); } catch (Exception e) { // never crash - catch them all - loge("Exception resetting dns cache: " + e); + if (DBG) loge("Exception resetting dns cache: " + e); } } } @@ -1840,12 +1860,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { // remove the default route unless somebody else has asked for it String ifaceName = newLp.getInterfaceName(); if (TextUtils.isEmpty(ifaceName) == false && mAddedRoutes.contains(r) == false) { - if (DBG) log("Removing " + r + " for interface " + ifaceName); + if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { mNetd.removeRoute(ifaceName, r); } catch (Exception e) { // never crash - catch them all - loge("Exception trying to remove a route: " + e); + if (VDBG) loge("Exception trying to remove a route: " + e); } } } @@ -2059,7 +2079,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses)); mNetd.setDefaultInterfaceForDns(iface); } catch (Exception e) { - loge("exception setting default dns interface: " + e); + if (VDBG) loge("exception setting default dns interface: " + e); } } if (!domains.equals(SystemProperties.get("net.dns.search"))) { @@ -2089,7 +2109,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetd.setDnsServersForInterface(p.getInterfaceName(), NetworkUtils.makeStrings(dnses)); } catch (Exception e) { - loge("exception setting dns servers: " + e); + if (VDBG) loge("exception setting dns servers: " + e); } // set per-pid dns for attached secondary nets List pids = mNetRequestersPids[netType]; @@ -2194,9 +2214,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { int type = info.getType(); NetworkInfo.State state = info.getState(); - if (DBG) log("ConnectivityChange for " + + if (VDBG || (state == NetworkInfo.State.CONNECTED) || + (state == NetworkInfo.State.DISCONNECTED)) { + log("ConnectivityChange for " + info.getTypeName() + ": " + state + "/" + info.getDetailedState()); + } // Connectivity state changed: // [31-13] Reserved for future use @@ -2458,23 +2481,24 @@ public class ConnectivityService extends IConnectivityManager.Stub { } private void handleInetConditionChange(int netType, int condition) { - if (DBG) { - log("Inet connectivity change, net=" + - netType + ", condition=" + condition + - ",mActiveDefaultNetwork=" + mActiveDefaultNetwork); - } if (mActiveDefaultNetwork == -1) { - if (DBG) log("no active default network - aborting"); + if (DBG) log("handleInetConditionChange: no active default network - ignore"); return; } if (mActiveDefaultNetwork != netType) { - if (DBG) log("given net not default - aborting"); + if (DBG) log("handleInetConditionChange: net=" + netType + + " != default=" + mActiveDefaultNetwork + " - ignore"); return; } + if (VDBG) { + log("handleInetConditionChange: net=" + + netType + ", condition=" + condition + + ",mActiveDefaultNetwork=" + mActiveDefaultNetwork); + } mDefaultInetCondition = condition; int delay; if (mInetConditionChangeInFlight == false) { - if (VDBG) log("starting a change hold"); + if (VDBG) log("handleInetConditionChange: starting a change hold"); // setup a new hold to debounce this if (mDefaultInetCondition > 50) { delay = Settings.Secure.getInt(mContext.getContentResolver(), @@ -2487,26 +2511,25 @@ public class ConnectivityService extends IConnectivityManager.Stub { mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END, mActiveDefaultNetwork, mDefaultConnectionSequence), delay); } else { - // we've set the new condition, when this hold ends that will get - // picked up - if (VDBG) log("currently in hold - not setting new end evt"); + // we've set the new condition, when this hold ends that will get picked up + if (VDBG) log("handleInetConditionChange: currently in hold - not setting new end evt"); } } private void handleInetConditionHoldEnd(int netType, int sequence) { - if (VDBG) { - log("Inet hold end, net=" + netType + - ", condition =" + mDefaultInetCondition + - ", published condition =" + mDefaultInetConditionPublished); + if (DBG) { + log("handleInetConditionHoldEnd: net=" + netType + + ", condition=" + mDefaultInetCondition + + ", published condition=" + mDefaultInetConditionPublished); } mInetConditionChangeInFlight = false; if (mActiveDefaultNetwork == -1) { - if (DBG) log("no active default network - aborting"); + if (DBG) log("handleInetConditionHoldEnd: no active default network - ignoring"); return; } if (mDefaultConnectionSequence != sequence) { - if (DBG) log("event hold for obsolete network - aborting"); + if (DBG) log("handleInetConditionHoldEnd: event hold for obsolete network - ignoring"); return; } // TODO: Figure out why this optimization sometimes causes a @@ -2518,7 +2541,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { //} NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); if (networkInfo.isConnected() == false) { - if (DBG) log("default network not connected - aborting"); + if (DBG) log("handleInetConditionHoldEnd: default network not connected - ignoring"); return; } mDefaultInetConditionPublished = mDefaultInetCondition; @@ -2596,7 +2619,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } if (VDBG) log("changing default proxy to " + proxy); - if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return; + + // global trumps default, if set, ignore this. if (mGlobalProxy != null) return; sendProxyBroadcast(proxy); } diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 146bc944724d..bc145b1274d1 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1362,13 +1362,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mInputShown = true; res = true; } else if (mHaveConnection && SystemClock.uptimeMillis() - < (mLastBindTime+TIME_TO_RECONNECT)) { + >= (mLastBindTime+TIME_TO_RECONNECT)) { // The client has asked to have the input method shown, but // we have been sitting here too long with a connection to the // service and no interface received, so let's disconnect/connect // to try to prod things along. EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime,1); + Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()"); mContext.unbindService(this); mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE); } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 0cffb15b3758..aacaa6a5a09e 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -508,6 +508,28 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + public void enableIpv6(String iface) throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + try { + mConnector.doCommand(String.format("interface ipv6 %s enable", iface)); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for enabling ipv6"); + } + } + + public void disableIpv6(String iface) throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + try { + mConnector.doCommand(String.format("interface ipv6 %s disable", iface)); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for disabling ipv6"); + } + } + public void addRoute(String interfaceName, RouteInfo route) { modifyRoute(interfaceName, ADD, route); } @@ -560,8 +582,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub + e); } - for (String line : rsp) { - Log.v(TAG, "add route response is " + line); + if (DBG) { + for (String line : rsp) { + Log.v(TAG, "add route response is " + line); + } } } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 0934cd02f8bd..78dbbd6eb555 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -79,6 +79,8 @@ public class PowerManagerService extends IPowerManager.Stub private static final String TAG = "PowerManagerService"; static final String PARTIAL_NAME = "PowerManagerService"; + static final boolean DEBUG_SCREEN_ON = false; + private static final boolean LOG_PARTIAL_WL = false; // Indicates whether touch-down cycles should be logged as part of the @@ -162,6 +164,8 @@ public class PowerManagerService extends IPowerManager.Stub private final int[] mBroadcastQueue = new int[] { -1, -1, -1 }; private final int[] mBroadcastWhy = new int[3]; private boolean mPreparingForScreenOn = false; + private boolean mSkippedScreenOn = false; + private boolean mInitialized = false; private int mPartialCount = 0; private int mPowerState; // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER, @@ -557,6 +561,10 @@ public class PowerManagerService extends IPowerManager.Stub nativeInit(); synchronized (mLocks) { updateNativePowerStateLocked(); + // We make sure to start out with the screen on due to user activity. + // (They did just boot their device, after all.) + forceUserActivityLocked(); + mInitialized = true; } } @@ -1123,7 +1131,8 @@ public class PowerManagerService extends IPowerManager.Stub + " " + ((mNextTimeout-now)/1000) + "s from now"); pw.println(" mDimScreen=" + mDimScreen + " mStayOnConditions=" + mStayOnConditions - + " mPreparingForScreenOn=" + mPreparingForScreenOn); + + " mPreparingForScreenOn=" + mPreparingForScreenOn + + " mSkippedScreenOn=" + mSkippedScreenOn); pw.println(" mScreenOffReason=" + mScreenOffReason + " mUserState=" + mUserState); pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1] @@ -1312,8 +1321,23 @@ public class PowerManagerService extends IPowerManager.Stub } } - private void sendNotificationLocked(boolean on, int why) - { + private void sendNotificationLocked(boolean on, int why) { + if (!mInitialized) { + // No notifications sent until first initialization is done. + // This is so that when we are moving from our initial state + // which looks like the screen was off to it being on, we do not + // go through the process of waiting for the higher-level user + // space to be ready before turning up the display brightness. + // (And also do not send needless broadcasts about the screen.) + return; + } + + if (DEBUG_SCREEN_ON) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "sendNotificationLocked: " + on, here); + } + if (!on) { mStillNeedSleepNotification = false; } @@ -1360,7 +1384,9 @@ public class PowerManagerService extends IPowerManager.Stub // The broadcast queue has changed; make sure the screen is on if it // is now possible for it to be. - updateNativePowerStateLocked(); + if (mSkippedScreenOn) { + updateLightsLocked(mPowerState, SCREEN_ON_BIT); + } // Now send the message. if (index >= 0) { @@ -1380,7 +1406,7 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (mLocks) { if (mPreparingForScreenOn) { mPreparingForScreenOn = false; - updateNativePowerStateLocked(); + updateLightsLocked(mPowerState, SCREEN_ON_BIT); EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 4, mBroadcastWakeLock.mCount); mBroadcastWakeLock.release(); @@ -1453,7 +1479,7 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (mLocks) { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, mBroadcastWakeLock.mCount); - updateNativePowerStateLocked(); + updateLightsLocked(mPowerState, SCREEN_ON_BIT); mBroadcastWakeLock.release(); } } @@ -1646,6 +1672,11 @@ public class PowerManagerService extends IPowerManager.Stub }; private int setScreenStateLocked(boolean on) { + if (DEBUG_SCREEN_ON) { + RuntimeException e = new RuntimeException("here"); + e.fillInStackTrace(); + Slog.i(TAG, "Set screen state: " + on, e); + } int err = Power.setScreenState(on); if (err == 0) { mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0); @@ -1696,7 +1727,7 @@ public class PowerManagerService extends IPowerManager.Stub } else { newState &= ~BATTERY_LOW_BIT; } - if (newState == mPowerState) { + if (newState == mPowerState && mInitialized) { return; } @@ -1722,10 +1753,7 @@ public class PowerManagerService extends IPowerManager.Stub + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0)); } - if (mPowerState != newState) { - updateLightsLocked(newState, 0); - mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK); - } + final boolean stateChanged = mPowerState != newState; if (oldScreenOn != newScreenOn) { if (newScreenOn) { @@ -1777,10 +1805,24 @@ public class PowerManagerService extends IPowerManager.Stub EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason, mTotalTouchDownTime, mTouchCycles); if (err == 0) { - mPowerState |= SCREEN_ON_BIT; sendNotificationLocked(true, -1); + // Update the lights *after* taking care of turning the + // screen on, so we do this after our notifications are + // enqueued and thus will delay turning on the screen light + // until the windows are correctly displayed. + if (stateChanged) { + updateLightsLocked(newState, 0); + } + mPowerState |= SCREEN_ON_BIT; } + } else { + // Update the lights *before* taking care of turning the + // screen off, so we can initiate any animations that are desired. + if (stateChanged) { + updateLightsLocked(newState, 0); + } + // cancel light sensor task mHandler.removeCallbacks(mAutoBrightnessTask); mLightSensorPendingDecrease = false; @@ -1803,30 +1845,18 @@ public class PowerManagerService extends IPowerManager.Stub mLastTouchDown = 0; } } + } else if (stateChanged) { + // Screen on/off didn't change, but lights may have. + updateLightsLocked(newState, 0); } - + + mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK); + updateNativePowerStateLocked(); } } - + private void updateNativePowerStateLocked() { - if ((mPowerState & SCREEN_ON_BIT) != 0) { - // Don't turn screen on until we know we are really ready to. - // This is to avoid letting the screen go on before things like the - // lock screen have been displayed. - if (mPreparingForScreenOn) { - // Currently waiting for confirmation from the policy that it - // is okay to turn on the screen. Don't allow the screen to go - // on until that is done. - return; - } - for (int i=0; i<mBroadcastQueue.length; i++) { - if (mBroadcastQueue[i] == 1) { - // A screen on is currently enqueued. - return; - } - } - } nativeSetPowerState( (mPowerState & SCREEN_ON_BIT) != 0, (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT); @@ -1852,8 +1882,43 @@ public class PowerManagerService extends IPowerManager.Stub mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD); } + private boolean shouldDeferScreenOnLocked() { + if (mPreparingForScreenOn) { + // Currently waiting for confirmation from the policy that it + // is okay to turn on the screen. Don't allow the screen to go + // on until that is done. + if (DEBUG_SCREEN_ON) Slog.i(TAG, + "updateLights: delaying screen on due to mPreparingForScreenOn"); + return true; + } else { + // If there is a screen-on command in the notification queue, we + // can't turn the screen on until it has been processed (and we + // have set mPreparingForScreenOn) or it has been dropped. + for (int i=0; i<mBroadcastQueue.length; i++) { + if (mBroadcastQueue[i] == 1) { + if (DEBUG_SCREEN_ON) Slog.i(TAG, + "updateLights: delaying screen on due to notification queue"); + return true; + } + } + } + return false; + } + private void updateLightsLocked(int newState, int forceState) { final int oldState = mPowerState; + + // If the screen is not currently on, we will want to delay actually + // turning the lights on if we are still getting the UI put up. + if ((oldState&SCREEN_ON_BIT) == 0 || mSkippedScreenOn) { + // Don't turn screen on until we know we are really ready to. + // This is to avoid letting the screen go on before things like the + // lock screen have been displayed. + if ((mSkippedScreenOn=shouldDeferScreenOnLocked())) { + newState &= ~(SCREEN_ON_BIT|SCREEN_BRIGHT_BIT); + } + } + if ((newState & SCREEN_ON_BIT) != 0) { // Only turn on the buttons or keyboard if the screen is also on. // We should never see the buttons on but not the screen. @@ -1960,6 +2025,13 @@ public class PowerManagerService extends IPowerManager.Stub } mScreenBrightness.setTargetLocked(brightness, steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); + if (DEBUG_SCREEN_ON) { + RuntimeException e = new RuntimeException("here"); + e.fillInStackTrace(); + Slog.i(TAG, "Setting screen brightness: " + brightness, e); + mScreenBrightness.setTargetLocked(brightness, steps, + INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); + } } if (mSpew) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 977dd6f5d54f..5006de757cd3 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -65,6 +65,7 @@ import java.util.TimerTask; class ServerThread extends Thread { private static final String TAG = "SystemServer"; private static final String ENCRYPTING_STATE = "trigger_restart_min_framework"; + private static final String ENCRYPTED_STATE = "1"; ContentResolver mContentResolver; @@ -150,10 +151,15 @@ class ServerThread extends Thread { Slog.i(TAG, "Package Manager"); // Only run "core" apps if we're encrypting the device. String cryptState = SystemProperties.get("vold.decrypt"); - boolean onlyCore = ENCRYPTING_STATE.equals(cryptState); - if (onlyCore) { + boolean onlyCore = false; + if (ENCRYPTING_STATE.equals(cryptState)) { Slog.w(TAG, "Detected encryption in progress - only parsing core apps"); + onlyCore = true; + } else if (ENCRYPTED_STATE.equals(cryptState)) { + Slog.w(TAG, "Device encrypted - only parsing core apps"); + onlyCore = true; } + pm = PackageManagerService.main(context, factoryTest != SystemServer.FACTORY_TEST_OFF, onlyCore); @@ -364,7 +370,8 @@ class ServerThread extends Thread { try { Slog.i(TAG, "Connectivity Service"); - connectivity = new ConnectivityService(context, networkManagement, networkPolicy); + connectivity = new ConnectivityService( + context, networkManagement, networkStats, networkPolicy); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity); networkStats.bindConnectivityManager(connectivity); networkPolicy.bindConnectivityManager(connectivity); diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java index bc256ed28162..8c8e72500689 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/java/com/android/server/TelephonyRegistry.java @@ -53,6 +53,7 @@ import com.android.server.am.BatteryStatsService; */ class TelephonyRegistry extends ITelephonyRegistry.Stub { private static final String TAG = "TelephonyRegistry"; + private static final boolean DBG = false; private static class Record { String pkgForDebug; @@ -387,9 +388,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyDataConnection()" )) { return; } - Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible=" + if (DBG) { + Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible=" + isDataConnectivityPossible + " reason='" + reason + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType); + } synchronized (mRecords) { boolean modified = false; if (state == TelephonyManager.DATA_CONNECTED) { @@ -421,8 +424,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { modified = true; } if (modified) { - Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState + if (DBG) { + Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState + ", " + mDataConnectionNetworkType + ")"); + } for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { try { @@ -639,7 +644,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } String msg = "Modify Phone State Permission Denial: " + method + " from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid(); - Slog.w(TAG, msg); + if (DBG) Slog.w(TAG, msg); return false; } diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java index c792b33bf2b4..ef48b9e2bc30 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -238,7 +238,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } else if (scs.hashCode() == hashCode) { if (DBG) { - Slog.w(TAG, "Return subtype " + scs.hashCode()); + Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale + + ", " + scs.getLocale()); } return scs; } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 41af1373db06..d038d767828d 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1318,6 +1318,14 @@ public final class ActivityManagerService extends ActivityManagerNative @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump meminfo from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args); } } @@ -1330,6 +1338,14 @@ public final class ActivityManagerService extends ActivityManagerNative @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump gfxinfo from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args); } } @@ -1342,6 +1358,14 @@ public final class ActivityManagerService extends ActivityManagerNative @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump cpuinfo from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + synchronized (mActivityManagerService.mProcessStatsThread) { pw.print(mActivityManagerService.mProcessStats.printCurrentLoad()); pw.print(mActivityManagerService.mProcessStats.printCurrentState( @@ -1631,8 +1655,8 @@ public final class ActivityManagerService extends ActivityManagerNative } if (app.conProviders.size() > 0) { for (ContentProviderRecord cpr : app.conProviders.keySet()) { - if (cpr.app != null && cpr.app.lruSeq != mLruSeq) { - updateLruProcessInternalLocked(cpr.app, oomAdj, + if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) { + updateLruProcessInternalLocked(cpr.proc, oomAdj, updateActivityTime, i+1); } } @@ -3334,6 +3358,11 @@ public final class ActivityManagerService extends ActivityManagerNative if ((samePackage || r.task == lastTask) && (r.app == null || evenPersistent || !r.app.persistent)) { if (!doit) { + if (r.finishing) { + // If this activity is just finishing, then it is not + // interesting as far as something to stop. + continue; + } return true; } didSomething = true; @@ -3373,7 +3402,24 @@ public final class ActivityManagerService extends ActivityManagerNative for (i=0; i<N; i++) { bringDownServiceLocked(services.get(i), true); } - + + ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>(); + for (ContentProviderRecord provider : mProvidersByClass.values()) { + if (provider.info.packageName.equals(name) + && (provider.proc == null || evenPersistent || !provider.proc.persistent)) { + if (!doit) { + return true; + } + didSomething = true; + providers.add(provider); + } + } + + N = providers.size(); + for (i=0; i<N; i++) { + removeDyingProviderLocked(null, providers.get(i)); + } + if (doit) { if (purgeCache) { AttributeCache ac = AttributeCache.instance(); @@ -3382,6 +3428,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } mMainStack.resumeTopActivityLocked(null); + mMainStack.scheduleIdleLocked(); } return didSomething; @@ -3761,6 +3808,12 @@ public final class ActivityManagerService extends ActivityManagerNative mWindowManager.showBootMessage(msg, always); } + public void dismissKeyguardOnNextActivity() { + synchronized (this) { + mMainStack.dismissKeyguardOnNextActivityLocked(); + } + } + final void finishBooting() { IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); @@ -5485,7 +5538,7 @@ public final class ActivityManagerService extends ActivityManagerNative ComponentName comp = new ComponentName(cpi.packageName, cpi.name); ContentProviderRecord cpr = mProvidersByClass.get(comp); if (cpr == null) { - cpr = new ContentProviderRecord(cpi, app.info); + cpr = new ContentProviderRecord(cpi, app.info, comp); mProvidersByClass.put(comp, cpr); } app.pubProviders.put(cpi.name, cpr); @@ -5643,25 +5696,25 @@ public final class ActivityManagerService extends ActivityManagerNative // return it right away. final boolean countChanged = incProviderCount(r, cpr); if (countChanged) { - if (cpr.app != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { + if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { // If this is a perceptible app accessing the provider, // make sure to count it as being accessed and thus // back up on the LRU list. This is good because // content providers are often expensive to start. - updateLruProcessLocked(cpr.app, false, true); + updateLruProcessLocked(cpr.proc, false, true); } } - if (cpr.app != null) { + if (cpr.proc != null) { if (false) { if (cpr.name.flattenToShortString().equals( "com.android.providers.calendar/.CalendarProvider2")) { Slog.v(TAG, "****************** KILLING " + cpr.name.flattenToShortString()); - Process.killProcess(cpr.app.pid); + Process.killProcess(cpr.proc.pid); } } - boolean success = updateOomAdjLocked(cpr.app); + boolean success = updateOomAdjLocked(cpr.proc); if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success); // NOTE: there is still a race here where a signal could be // pending on the process even though we managed to update its @@ -5676,7 +5729,7 @@ public final class ActivityManagerService extends ActivityManagerNative "Existing provider " + cpr.name.flattenToShortString() + " is crashing; detaching " + r); boolean lastRef = decProviderCount(r, cpr); - appDiedLocked(cpr.app, cpr.app.pid, cpr.app.thread); + appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread); if (!lastRef) { // This wasn't the last ref our process had on // the provider... we have now been killed, bail. @@ -5729,7 +5782,7 @@ public final class ActivityManagerService extends ActivityManagerNative + cpi.name); return null; } - cpr = new ContentProviderRecord(cpi, ai); + cpr = new ContentProviderRecord(cpi, ai, comp); } catch (RemoteException ex) { // pm is in same process, this will never happen. } @@ -5864,7 +5917,7 @@ public final class ActivityManagerService extends ActivityManagerNative //update content provider record entry info ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name); ContentProviderRecord localCpr = mProvidersByClass.get(comp); - if (localCpr.app == r) { + if (localCpr.proc == r) { //should not happen. taken care of as a local provider Slog.w(TAG, "removeContentProvider called on local provider: " + cpr.info.name + " in process " + r.processName); @@ -5940,7 +5993,7 @@ public final class ActivityManagerService extends ActivityManagerNative } synchronized (dst) { dst.provider = src.provider; - dst.app = r; + dst.proc = r; dst.notifyAll(); } updateOomAdjLocked(r); @@ -7884,6 +7937,8 @@ public final class ActivityManagerService extends ActivityManagerNative if (dumpAll) { pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity); pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout); + pw.println(" mDismissKeyguardOnNextActivity: " + + mMainStack.mDismissKeyguardOnNextActivity); } if (mRecentTasks.size() > 0) { @@ -8524,7 +8579,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i<N; i++) { sb.setLength(0); sb.append(" Intent: "); - intents.get(i).toShortString(sb, true, false); + intents.get(i).toShortString(sb, false, true, false); pw.println(sb.toString()); Bundle bundle = intents.get(i).getExtras(); if (bundle != null) { @@ -8706,9 +8761,9 @@ public final class ActivityManagerService extends ActivityManagerNative r.dump(pw, " "); } else { pw.print(" * "); pw.print(e.getKey().flattenToShortString()); - if (r.app != null) { + if (r.proc != null) { pw.println(":"); - pw.print(" "); pw.println(r.app); + pw.print(" "); pw.println(r.proc); } else { pw.println(); } @@ -8817,7 +8872,8 @@ public final class ActivityManagerService extends ActivityManagerNative } else if (complete) { // Complete + brief == give a summary. Isn't that obvious?!? if (lastTask.intent != null) { - pw.print(prefix); pw.print(" "); pw.println(lastTask.intent); + pw.print(prefix); pw.print(" "); + pw.println(lastTask.intent.toInsecureString()); } } } @@ -8828,7 +8884,7 @@ public final class ActivityManagerService extends ActivityManagerNative r.dump(pw, innerPrefix); } else if (complete) { // Complete + brief == give a summary. Isn't that obvious?!? - pw.print(innerPrefix); pw.println(r.intent); + pw.print(innerPrefix); pw.println(r.intent.toInsecureString()); if (r.app != null) { pw.print(innerPrefix); pw.println(r.app); } @@ -9440,7 +9496,7 @@ public final class ActivityManagerService extends ActivityManagerNative cpr.notifyAll(); } - mProvidersByClass.remove(cpr.info.name); + mProvidersByClass.remove(cpr.name); String names[] = cpr.info.authority.split(";"); for (int j = 0; j < names.length; j++) { mProvidersByName.remove(names[j]); @@ -9454,9 +9510,10 @@ public final class ActivityManagerService extends ActivityManagerNative && capp.pid != MY_PID) { Slog.i(TAG, "Kill " + capp.processName + " (pid " + capp.pid + "): provider " + cpr.info.name - + " in dying process " + proc.processName); + + " in dying process " + (proc != null ? proc.processName : "??")); EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid, - capp.processName, capp.setAdj, "dying provider " + proc.processName); + capp.processName, capp.setAdj, "dying provider " + + cpr.name.toShortString()); Process.killProcessQuiet(capp.pid); } } @@ -9515,7 +9572,7 @@ public final class ActivityManagerService extends ActivityManagerNative while (it.hasNext()) { ContentProviderRecord cpr = it.next(); cpr.provider = null; - cpr.app = null; + cpr.proc = null; // See if someone is waiting for this provider... in which // case we don't remove it, but just let it restart. @@ -10029,7 +10086,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean created = false; try { mStringBuilder.setLength(0); - r.intent.getIntent().toShortString(mStringBuilder, false, true); + r.intent.getIntent().toShortString(mStringBuilder, true, false, true); EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE, System.identityHashCode(r), r.shortName, mStringBuilder.toString(), r.app.pid); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 73ffafb66ec1..ce45bfb17ba9 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -122,7 +122,7 @@ final class ActivityRecord extends IApplicationToken.Stub { pw.print(" processName="); pw.println(processName); pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid); pw.print(" app="); pw.println(app); - pw.print(prefix); pw.println(intent); + pw.print(prefix); pw.println(intent.toInsecureString()); pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask); pw.print(" task="); pw.println(task); pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity); diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a0aedf984473..7bc19ab43882 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -259,6 +259,11 @@ final class ActivityStack { */ boolean mSleepTimeout = false; + /** + * Dismiss the keyguard after the next activity is displayed? + */ + boolean mDismissKeyguardOnNextActivity = false; + int mThumbnailWidth = -1; int mThumbnailHeight = -1; @@ -765,9 +770,7 @@ final class ActivityStack { // Still need to tell some activities to stop; can't sleep yet. if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop " + mStoppingActivities.size() + " activities"); - Message msg = Message.obtain(); - msg.what = IDLE_NOW_MSG; - mHandler.sendMessage(msg); + scheduleIdleLocked(); return; } @@ -978,9 +981,7 @@ final class ActivityStack { // then give up on things going idle and start clearing // them out. if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle"); - Message msg = Message.obtain(); - msg.what = IDLE_NOW_MSG; - mHandler.sendMessage(msg); + scheduleIdleLocked(); } else { checkReadyForSleepLocked(); } @@ -2173,7 +2174,7 @@ final class ActivityStack { } if (err == START_SUCCESS) { - Slog.i(TAG, "Starting: " + intent + " from pid " + Slog.i(TAG, "START {" + intent.toShortString(true, true, true) + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); } @@ -2228,6 +2229,7 @@ final class ActivityStack { resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } + mDismissKeyguardOnNextActivity = false; return err; } @@ -2239,6 +2241,7 @@ final class ActivityStack { resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } + mDismissKeyguardOnNextActivity = false; String msg; if (!aInfo.exported) { msg = "Permission Denial: starting " + intent.toString() @@ -2276,6 +2279,7 @@ final class ActivityStack { } // We pretend to the caller that it was really started, but // they will just get a cancel result. + mDismissKeyguardOnNextActivity = false; return START_SUCCESS; } } @@ -2299,6 +2303,7 @@ final class ActivityStack { pal.grantedMode = grantedMode; pal.onlyIfNeeded = onlyIfNeeded; mService.mPendingActivityLaunches.add(pal); + mDismissKeyguardOnNextActivity = false; return START_SWITCHES_CANCELED; } } @@ -2317,8 +2322,17 @@ final class ActivityStack { mService.doPendingActivityLaunchesLocked(false); } - return startActivityUncheckedLocked(r, sourceRecord, + err = startActivityUncheckedLocked(r, sourceRecord, grantedUriPermissions, grantedMode, onlyIfNeeded, true); + if (mDismissKeyguardOnNextActivity && mPausingActivity == null) { + // Someone asked to have the keyguard dismissed on the next + // activity start, but we are not actually doing an activity + // switch... just dismiss the keyguard now, because we + // probably want to see whatever is behind it. + mDismissKeyguardOnNextActivity = false; + mService.mWindowManager.dismissKeyguard(); + } + return err; } final void moveHomeToFrontFromLaunchLocked(int launchFlags) { @@ -2987,6 +3001,11 @@ final class ActivityStack { w.thisTime = w.totalTime; } mService.notifyAll(); + + if (mDismissKeyguardOnNextActivity) { + mDismissKeyguardOnNextActivity = false; + mService.mWindowManager.dismissKeyguard(); + } } void sendActivityResultLocked(int callingUid, ActivityRecord r, @@ -3103,6 +3122,12 @@ final class ActivityStack { return stops; } + final void scheduleIdleLocked() { + Message msg = Message.obtain(); + msg.what = IDLE_NOW_MSG; + mHandler.sendMessage(msg); + } + final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout, Configuration config) { if (localLOGV) Slog.v(TAG, "Activity idle: " + token); @@ -3413,9 +3438,7 @@ final class ActivityStack { // If we already have a few activities waiting to stop, // then give up on things going idle and start clearing // them out. - Message msg = Message.obtain(); - msg.what = IDLE_NOW_MSG; - mHandler.sendMessage(msg); + scheduleIdleLocked(); } else { checkReadyForSleepLocked(); } @@ -4126,4 +4149,8 @@ final class ActivityStack { return true; } + + public void dismissKeyguardOnNextActivityLocked() { + mDismissKeyguardOnNextActivity = true; + } } diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 226723fbed6c..b44dc8a2afad 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -21,6 +21,7 @@ import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.IBinder; import android.os.Parcel; @@ -457,6 +458,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump BatteryStats from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + boolean isCheckin = false; boolean noOutput = false; if (args != null) { diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java index db235ee849e2..9c55597530d2 100644 --- a/services/java/com/android/server/am/ContentProviderRecord.java +++ b/services/java/com/android/server/am/ContentProviderRecord.java @@ -32,15 +32,15 @@ class ContentProviderRecord extends ContentProviderHolder { final ApplicationInfo appInfo; final ComponentName name; int externals; // number of non-framework processes supported by this provider - ProcessRecord app; // if non-null, hosting application + ProcessRecord proc; // if non-null, hosting process. ProcessRecord launchingApp; // if non-null, waiting for this app to be launched. String stringName; - public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai) { + public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai, ComponentName _name) { super(_info); uid = ai.uid; appInfo = ai; - name = new ComponentName(_info.packageName, _info.name); + name = _name; noReleaseNeeded = uid == 0 || uid == Process.SYSTEM_UID; } @@ -61,7 +61,7 @@ class ContentProviderRecord extends ContentProviderHolder { pw.print(prefix); pw.print("package="); pw.print(info.applicationInfo.packageName); pw.print(" process="); pw.println(info.processName); - pw.print(prefix); pw.print("app="); pw.println(app); + pw.print(prefix); pw.print("proc="); pw.println(proc); if (launchingApp != null) { pw.print(prefix); pw.print("launchingApp="); pw.println(launchingApp); } diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java index 3a5ca669c827..2618c77e2b2d 100644 --- a/services/java/com/android/server/am/IntentBindRecord.java +++ b/services/java/com/android/server/am/IntentBindRecord.java @@ -54,7 +54,7 @@ class IntentBindRecord { void dumpInService(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("intent={"); - pw.print(intent.getIntent().toShortString(true, false)); + pw.print(intent.getIntent().toShortString(false, true, false)); pw.println('}'); pw.print(prefix); pw.print("binder="); pw.println(binder); pw.print(prefix); pw.print("requested="); pw.print(requested); @@ -89,7 +89,7 @@ class IntentBindRecord { sb.append(service.shortName); sb.append(':'); if (intent != null) { - intent.getIntent().toShortString(sb, false, false); + intent.getIntent().toShortString(sb, false, false, false); } sb.append('}'); return stringName = sb.toString(); diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java index 8ed0cc11abd8..abd2a1f1207d 100644 --- a/services/java/com/android/server/am/PendingIntentRecord.java +++ b/services/java/com/android/server/am/PendingIntentRecord.java @@ -150,7 +150,8 @@ class PendingIntentRecord extends IIntentSender.Stub { public String toString() { return "Key{" + typeName() + " pkg=" + packageName + " intent=" - + (requestIntent != null ? requestIntent.toShortString(true, false) : "<null>") + + (requestIntent != null + ? requestIntent.toShortString(false, true, false) : "<null>") + " flags=0x" + Integer.toHexString(flags) + "}"; } @@ -317,7 +318,7 @@ class PendingIntentRecord extends IIntentSender.Stub { } if (key.requestIntent != null) { pw.print(prefix); pw.print("requestIntent="); - pw.println(key.requestIntent.toShortString(true, true)); + pw.println(key.requestIntent.toShortString(false, true, true)); } if (sent || canceled) { pw.print(prefix); pw.print("sent="); pw.print(sent); diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index 004e963b27fe..257113bbe671 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -192,7 +192,7 @@ class ServiceRecord extends Binder { void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("intent={"); - pw.print(intent.getIntent().toShortString(true, false)); + pw.print(intent.getIntent().toShortString(false, true, false)); pw.println('}'); pw.print(prefix); pw.print("packageName="); pw.println(packageName); pw.print(prefix); pw.print("processName="); pw.println(processName); diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index 87129eaca73f..a86076344e8a 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -94,14 +94,14 @@ class TaskRecord extends ThumbnailHolder { if (intent != null) { StringBuilder sb = new StringBuilder(128); sb.append(prefix); sb.append("intent={"); - intent.toShortString(sb, true, false); + intent.toShortString(sb, false, true, false); sb.append('}'); pw.println(sb.toString()); } if (affinityIntent != null) { StringBuilder sb = new StringBuilder(128); sb.append(prefix); sb.append("affinityIntent={"); - affinityIntent.toShortString(sb, true, false); + affinityIntent.toShortString(sb, false, true, false); sb.append('}'); pw.println(sb.toString()); } diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java index 0d36d69cfc33..e810e3c5bf51 100644 --- a/services/java/com/android/server/am/UsageStatsService.java +++ b/services/java/com/android/server/am/UsageStatsService.java @@ -19,6 +19,7 @@ package com.android.server.am; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.IBinder; import android.os.FileUtils; @@ -1034,6 +1035,14 @@ public final class UsageStatsService extends IUsageStats.Stub { * The data persisted to file is parsed and the stats are computed. */ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump UsageStats from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + final boolean isCheckinRequest = scanArgs(args, "--checkin"); final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c"); final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d"); diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 52868242750f..6b9c08852124 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -29,6 +29,7 @@ import android.hardware.usb.UsbManager; import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; +import android.net.INetworkStatsService; import android.net.InterfaceConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; @@ -71,7 +72,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private Context mContext; private final static String TAG = "Tethering"; - private final static boolean DEBUG = true; + private final static boolean DBG = true; + private final static boolean VDBG = false; // TODO - remove both of these - should be part of interface inspection/selection stuff private String[] mTetherableUsbRegexs; @@ -87,7 +89,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { // upstream type list and the DUN_REQUIRED secure-setting private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE; - private INetworkManagementService mNMService; + private final INetworkManagementService mNMService; + private final INetworkStatsService mStatsService; private Looper mLooper; private HandlerThread mThread; @@ -123,9 +126,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private boolean mUsbTetherRequested; // true if USB tethering should be started // when RNDIS is enabled - public Tethering(Context context, INetworkManagementService nmService, Looper looper) { + public Tethering(Context context, INetworkManagementService nmService, + INetworkStatsService statsService, Looper looper) { mContext = context; mNMService = nmService; + mStatsService = statsService; mLooper = looper; mIfaces = new HashMap<String, TetherInterfaceSM>(); @@ -178,7 +183,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public void interfaceStatusChanged(String iface, boolean up) { - if (DEBUG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); + if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); boolean found = false; boolean usb = false; if (isWifi(iface)) { @@ -203,7 +208,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (isUsb(iface)) { // ignore usb0 down after enabling RNDIS // we will handle disconnect in interfaceRemoved instead - Log.d(TAG, "ignoring interface down for " + iface); + if (VDBG) Log.d(TAG, "ignoring interface down for " + iface); } else if (sm != null) { sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); mIfaces.remove(iface); @@ -213,7 +218,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public void interfaceLinkStateChanged(String iface, boolean up) { - if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up); + if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up); interfaceStatusChanged(iface, up); } @@ -239,7 +244,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public void interfaceAdded(String iface) { - if (DEBUG) Log.d(TAG, "interfaceAdded " + iface); + if (VDBG) Log.d(TAG, "interfaceAdded " + iface); boolean found = false; boolean usb = false; if (isWifi(iface)) { @@ -253,29 +258,29 @@ public class Tethering extends INetworkManagementEventObserver.Stub { found = true; } if (found == false) { - if (DEBUG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); + if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); return; } synchronized (mIfaces) { TetherInterfaceSM sm = mIfaces.get(iface); if (sm != null) { - if (DEBUG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring"); + if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring"); return; } sm = new TetherInterfaceSM(iface, mLooper, usb); mIfaces.put(iface, sm); sm.start(); } - if (DEBUG) Log.d(TAG, "interfaceAdded :" + iface); + if (VDBG) Log.d(TAG, "interfaceAdded :" + iface); } public void interfaceRemoved(String iface) { - if (DEBUG) Log.d(TAG, "interfaceRemoved " + iface); + if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); synchronized (mIfaces) { TetherInterfaceSM sm = mIfaces.get(iface); if (sm == null) { - if (DEBUG) { + if (VDBG) { Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring"); } return; @@ -288,7 +293,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public void limitReached(String limitName, String iface) {} public int tether(String iface) { - Log.d(TAG, "Tethering " + iface); + if (DBG) Log.d(TAG, "Tethering " + iface); TetherInterfaceSM sm = null; synchronized (mIfaces) { sm = mIfaces.get(iface); @@ -306,7 +311,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public int untether(String iface) { - Log.d(TAG, "Untethering " + iface); + if (DBG) Log.d(TAG, "Untethering " + iface); TetherInterfaceSM sm = null; synchronized (mIfaces) { sm = mIfaces.get(iface); @@ -383,7 +388,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList); mContext.sendStickyBroadcast(broadcast); - if (DEBUG) { + if (VDBG) { Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + activeList.size() + ", " + erroredList.size()); } @@ -468,14 +473,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub { mUsbTetherRequested = false; } } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { - if (DEBUG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); + if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); } } } private void tetherUsb(boolean enable) { - if (DEBUG) Log.d(TAG, "tetherUsb " + enable); + if (VDBG) Log.d(TAG, "tetherUsb " + enable); String[] ifaces = new String[0]; try { @@ -497,7 +502,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { // configured when we start tethering and unconfig'd on error or conclusion private boolean configureUsbIface(boolean enabled) { - if (DEBUG) Log.d(TAG, "configureUsbIface(" + enabled + ")"); + if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")"); // toggle the USB interfaces String[] ifaces = new String[0]; @@ -547,7 +552,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public int setUsbTethering(boolean enable) { - if (DEBUG) Log.d(TAG, "setUsbTethering(" + enable + ")"); + if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); synchronized (this) { @@ -808,7 +813,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { @Override public boolean processMessage(Message message) { - if (DEBUG) Log.d(TAG, "InitialState.processMessage what=" + message.what); + if (VDBG) Log.d(TAG, "InitialState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_REQUESTED: @@ -849,7 +854,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - if (DEBUG) Log.d(TAG, "StartingState.processMessage what=" + message.what); + if (VDBG) Log.d(TAG, "StartingState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { // maybe a parent class? @@ -897,14 +902,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub { transitionTo(mInitialState); return; } - if (DEBUG) Log.d(TAG, "Tethered " + mIfaceName); + if (DBG) Log.d(TAG, "Tethered " + mIfaceName); setAvailable(false); setTethered(true); sendTetherStateChangedBroadcast(); } @Override public boolean processMessage(Message message) { - if (DEBUG) Log.d(TAG, "TetheredState.processMessage what=" + message.what); + if (VDBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what); boolean retValue = true; boolean error = false; switch (message.what) { @@ -912,6 +917,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { case CMD_INTERFACE_DOWN: if (mMyUpstreamIfaceName != null) { try { + // about to tear down NAT; gather remaining statistics + mStatsService.forceUpdate(); + mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName); mMyUpstreamIfaceName = null; } catch (Exception e) { @@ -944,18 +952,21 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } else if (message.what == CMD_INTERFACE_DOWN) { transitionTo(mUnavailableState); } - if (DEBUG) Log.d(TAG, "Untethered " + mIfaceName); + if (DBG) Log.d(TAG, "Untethered " + mIfaceName); break; case CMD_TETHER_CONNECTION_CHANGED: String newUpstreamIfaceName = (String)(message.obj); if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) || (mMyUpstreamIfaceName != null && mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) { - if (DEBUG) Log.d(TAG, "Connection changed noop - dropping"); + if (VDBG) Log.d(TAG, "Connection changed noop - dropping"); break; } if (mMyUpstreamIfaceName != null) { try { + // about to tear down NAT; gather remaining statistics + mStatsService.forceUpdate(); + mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName); mMyUpstreamIfaceName = null; } catch (Exception e) { @@ -994,6 +1005,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { case CMD_TETHER_MODE_DEAD: if (mMyUpstreamIfaceName != null) { try { + // about to tear down NAT; gather remaining statistics + mStatsService.forceUpdate(); + mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName); mMyUpstreamIfaceName = null; } catch (Exception e) { @@ -1018,7 +1032,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { ConnectivityManager.TETHER_ERROR_MASTER_ERROR); break; } - if (DEBUG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName); + if (VDBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName); sendTetherStateChangedBroadcast(); if (mUsb) { if (!Tethering.this.configureUsbIface(false)) { @@ -1248,7 +1262,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } } - if (DEBUG) { + if (VDBG) { Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn =" + mPreferredUpstreamMobileApn + ", got type=" + upType); } @@ -1280,7 +1294,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { - if (DEBUG) Log.d(TAG, "notifying tethered with iface =" + ifaceName); + if (VDBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName); mUpstreamIfaceName = ifaceName; for (Object o : mNotifyList) { TetherInterfaceSM sm = (TetherInterfaceSM)o; @@ -1296,19 +1310,19 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - if (DEBUG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); + if (VDBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_MODE_REQUESTED: checkDunRequired(); TetherInterfaceSM who = (TetherInterfaceSM)message.obj; - if (DEBUG) Log.d(TAG, "Tether Mode requested by " + who.toString()); + if (VDBG) Log.d(TAG, "Tether Mode requested by " + who.toString()); mNotifyList.add(who); transitionTo(mTetherModeAliveState); break; case CMD_TETHER_MODE_UNREQUESTED: who = (TetherInterfaceSM)message.obj; - if (DEBUG) Log.d(TAG, "Tether Mode unrequested by " + who.toString()); + if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who.toString()); int index = mNotifyList.indexOf(who); if (index != -1) { mNotifyList.remove(who); @@ -1339,7 +1353,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - if (DEBUG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); + if (VDBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_MODE_REQUESTED: @@ -1368,7 +1382,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { // make sure we're still using a requested connection - may have found // wifi or something since then. if (mCurrentConnectionSequence == message.arg1) { - if (DEBUG) { + if (VDBG) { Log.d(TAG, "renewing mobile connection - requeuing for another " + CELL_CONNECTION_RENEW_MS + "ms"); } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index bc65205cbe10..aa46795b4fb9 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -24,8 +24,8 @@ import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.EXTRA_UID; -import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; +import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; @@ -43,9 +43,12 @@ import static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL; import static android.provider.Settings.Secure.NETSTATS_TAG_MAX_HISTORY; import static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION; import static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY; +import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE; +import static android.telephony.PhoneStateListener.LISTEN_NONE; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; +import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; @@ -80,6 +83,7 @@ import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; +import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.EventLog; import android.util.Log; @@ -121,7 +125,7 @@ import libcore.io.IoUtils; */ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String TAG = "NetworkStats"; - private static final boolean LOGD = true; + private static final boolean LOGD = false; private static final boolean LOGV = false; /** File header magic number: "ANET" */ @@ -132,7 +136,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int VERSION_UID_WITH_TAG = 3; private static final int VERSION_UID_WITH_SET = 4; - private static final int MSG_PERFORM_POLL = 0x1; + private static final int MSG_PERFORM_POLL = 1; + private static final int MSG_UPDATE_IFACES = 2; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x10; @@ -144,6 +149,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final INetworkManagementService mNetworkManager; private final IAlarmManager mAlarmManager; private final TrustedTime mTime; + private final TelephonyManager mTeleManager; private final NetworkStatsSettings mSettings; private final PowerManager.WakeLock mWakeLock; @@ -227,6 +233,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService"); mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager"); mTime = checkNotNull(time, "missing TrustedTime"); + mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager"); mSettings = checkNotNull(settings, "missing NetworkStatsSettings"); final PowerManager powerManager = (PowerManager) context.getSystemService( @@ -279,6 +286,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // ignored; service lives in system_server } + // watch for networkType changes that aren't broadcast through + // CONNECTIVITY_ACTION_IMMEDIATE above. + mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE); + registerPollAlarmLocked(); registerGlobalAlert(); @@ -288,10 +299,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void shutdownLocked() { mContext.unregisterReceiver(mConnReceiver); + mContext.unregisterReceiver(mTetherReceiver); mContext.unregisterReceiver(mPollReceiver); mContext.unregisterReceiver(mRemovedReceiver); mContext.unregisterReceiver(mShutdownReceiver); + mTeleManager.listen(mPhoneListener, LISTEN_NONE); + writeNetworkStatsLocked(); if (mUidStatsLoaded) { writeUidStatsLocked(); @@ -535,14 +549,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void onReceive(Context context, Intent intent) { // on background handler thread, and verified CONNECTIVITY_INTERNAL // permission above. - synchronized (mStatsLock) { - mWakeLock.acquire(); - try { - updateIfacesLocked(); - } finally { - mWakeLock.release(); - } - } + updateIfaces(); } }; @@ -619,6 +626,46 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; + private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN; + private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + + /** + * Receiver that watches for {@link TelephonyManager} changes, such as + * transitioning between network types. + */ + private PhoneStateListener mPhoneListener = new PhoneStateListener() { + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + final boolean stateChanged = state != mLastPhoneState; + final boolean networkTypeChanged = networkType != mLastPhoneNetworkType; + + if (networkTypeChanged && !stateChanged) { + // networkType changed without a state change, which means we + // need to roll our own update. delay long enough for + // ConnectivityManager to process. + // TODO: add direct event to ConnectivityService instead of + // relying on this delay. + if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()"); + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); + } + + mLastPhoneState = state; + mLastPhoneNetworkType = networkType; + } + }; + + private void updateIfaces() { + synchronized (mStatsLock) { + mWakeLock.acquire(); + try { + updateIfacesLocked(); + } finally { + mWakeLock.release(); + } + } + } + /** * Inspect all current {@link NetworkState} to derive mapping from {@code * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo} @@ -713,19 +760,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final long threshold = mSettings.getPersistThreshold(); try { - // record network stats - final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary(); - performNetworkPollLocked(networkSnapshot, currentTime); - - // persist when enough network data has occurred - final NetworkStats persistNetworkDelta = computeStatsDelta( - mLastPersistNetworkSnapshot, networkSnapshot, true); - final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold; - if (persistForce || (persistNetwork && networkPastThreshold)) { - writeNetworkStatsLocked(); - mLastPersistNetworkSnapshot = networkSnapshot; - } - // record tethering stats; persisted during normal UID cycle below final String[] ifacePairs = mConnManager.getTetheredIfacePairs(); final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering( @@ -744,6 +778,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { writeUidStatsLocked(); mLastPersistUidSnapshot = uidSnapshot; } + + // record network stats + final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary(); + performNetworkPollLocked(networkSnapshot, currentTime); + + // persist when enough network data has occurred + final NetworkStats persistNetworkDelta = computeStatsDelta( + mLastPersistNetworkSnapshot, networkSnapshot, true); + final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold; + if (persistForce || (persistNetwork && networkPastThreshold)) { + writeNetworkStatsLocked(); + mLastPersistNetworkSnapshot = networkSnapshot; + } } catch (IllegalStateException e) { Log.wtf(TAG, "problem reading network stats", e); } catch (RemoteException e) { @@ -1356,6 +1403,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performPoll(flags); return true; } + case MSG_UPDATE_IFACES: { + updateIfaces(); + return true; + } default: { return false; } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 9ebdd52ad47d..eb135b7c41a0 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -72,6 +72,7 @@ import android.content.pm.Signature; import android.content.pm.UserInfo; import android.content.pm.ManifestDigest; import android.content.pm.VerifierDeviceIdentity; +import android.content.pm.VerifierInfo; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -113,6 +114,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.CertificateException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; @@ -158,6 +161,7 @@ public class PackageManagerService extends IPackageManager.Stub { private static final boolean DEBUG_INTENT_MATCHING = false; private static final boolean DEBUG_PACKAGE_SCANNING = false; private static final boolean DEBUG_APP_DIR_OBSERVER = false; + private static final boolean DEBUG_VERIFY = false; static final boolean MULTIPLE_APPLICATION_UIDS = true; private static final int RADIO_UID = Process.PHONE_UID; @@ -208,6 +212,8 @@ public class PackageManagerService extends IPackageManager.Stub { DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService"); + private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; + private static final String LIB_DIR_NAME = "lib"; static final String mTempContainerPrefix = "smdl2tmp"; @@ -349,7 +355,8 @@ public class PackageManagerService extends IPackageManager.Stub { final HashSet<String> mProtectedBroadcasts = new HashSet<String>(); /** List of packages waiting for verification. */ - final SparseArray<InstallArgs> mPendingVerification = new SparseArray<InstallArgs>(); + final SparseArray<PackageVerificationState> mPendingVerification + = new SparseArray<PackageVerificationState>(); final ArrayList<PackageParser.Package> mDeferredDexOpt = new ArrayList<PackageParser.Package>(); @@ -427,6 +434,8 @@ public class PackageManagerService extends IPackageManager.Stub { final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>(); int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows + private final String mRequiredVerifierPackage; + class PackageHandler extends Handler { private boolean mBound = false; final ArrayList<HandlerParams> mPendingInstalls = @@ -740,9 +749,10 @@ public class PackageManagerService extends IPackageManager.Stub { } break; case CHECK_PENDING_VERIFICATION: { final int verificationId = msg.arg1; - final InstallArgs args = mPendingVerification.get(verificationId); + final PackageVerificationState state = mPendingVerification.get(verificationId); - if (args != null) { + if (state != null) { + final InstallArgs args = state.getInstallArgs(); Slog.i(TAG, "Validation timed out for " + args.packageURI.toString()); mPendingVerification.remove(verificationId); @@ -756,31 +766,38 @@ public class PackageManagerService extends IPackageManager.Stub { } case PACKAGE_VERIFIED: { final int verificationId = msg.arg1; - final boolean verified = msg.arg2 == 1 ? true : false; - final InstallArgs args = mPendingVerification.get(verificationId); - if (args == null) { + final PackageVerificationState state = mPendingVerification.get(verificationId); + if (state == null) { Slog.w(TAG, "Invalid validation token " + verificationId + " received"); break; } - mPendingVerification.remove(verificationId); + final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj; - int ret; - if (verified) { - ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; - try { - ret = args.copyApk(mContainerService, true); - } catch (RemoteException e) { - Slog.e(TAG, "Could not contact the ContainerService"); + state.setVerifierResponse(response.callerUid, response.code); + + if (state.isVerificationComplete()) { + mPendingVerification.remove(verificationId); + + final InstallArgs args = state.getInstallArgs(); + + int ret; + if (state.isInstallAllowed()) { + ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; + try { + ret = args.copyApk(mContainerService, true); + } catch (RemoteException e) { + Slog.e(TAG, "Could not contact the ContainerService"); + } + } else { + ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE; } - } else { - ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE; - } - processPendingInstall(args, ret); + processPendingInstall(args, ret); - mHandler.sendEmptyMessage(MCS_UNBIND); + mHandler.sendEmptyMessage(MCS_UNBIND); + } break; } @@ -945,7 +962,8 @@ public class PackageManagerService extends IPackageManager.Stub { } catch (FileNotFoundException e) { Slog.w(TAG, "Boot class path not found: " + paths[i]); } catch (IOException e) { - Slog.w(TAG, "Exception reading boot class path: " + paths[i], e); + Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? " + + e.getMessage()); } } } else { @@ -968,7 +986,8 @@ public class PackageManagerService extends IPackageManager.Stub { } catch (FileNotFoundException e) { Slog.w(TAG, "Library not found: " + lib); } catch (IOException e) { - Slog.w(TAG, "Exception reading library: " + lib, e); + Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? " + + e.getMessage()); } } } @@ -1132,10 +1151,49 @@ public class PackageManagerService extends IPackageManager.Stub { // are all flushed. Not really needed, but keeps things nice and // tidy. Runtime.getRuntime().gc(); + + mRequiredVerifierPackage = getRequiredVerifierLPr(); } // synchronized (mPackages) } // synchronized (mInstallLock) } + private String getRequiredVerifierLPr() { + final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); + final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE, + PackageManager.GET_DISABLED_COMPONENTS); + + String requiredVerifier = null; + + final int N = receivers.size(); + for (int i = 0; i < N; i++) { + final ResolveInfo info = receivers.get(i); + + if (info.activityInfo == null) { + continue; + } + + final String packageName = info.activityInfo.packageName; + + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps == null) { + continue; + } + + if (!ps.grantedPermissions + .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) { + continue; + } + + if (requiredVerifier != null) { + throw new RuntimeException("There can be only one required verifier"); + } + + requiredVerifier = packageName; + } + + return requiredVerifier; + } + @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { @@ -4350,7 +4408,10 @@ public class PackageManagerService extends IPackageManager.Stub { if (p != null) { PackageSetting ps = (PackageSetting)p.mExtras; if (ps != null) { - return ps.stopped; + // System apps are never considered stopped for purposes of + // filtering, because there may be no way for the user to + // actually re-launch them. + return ps.stopped && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0; } } return false; @@ -4522,7 +4583,10 @@ public class PackageManagerService extends IPackageManager.Stub { if (p != null) { PackageSetting ps = (PackageSetting)p.mExtras; if (ps != null) { - return ps.stopped; + // System apps are never considered stopped for purposes of + // filtering, because there may be no way for the user to + // actually re-launch them. + return ps.stopped && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0; } } return false; @@ -4849,18 +4913,110 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public void verifyPendingInstall(int id, boolean verified, String message) - throws RemoteException { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, null); - + public void verifyPendingInstall(int id, int verificationCode) throws RemoteException { final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED); + final PackageVerificationResponse response = new PackageVerificationResponse( + verificationCode, Binder.getCallingUid()); msg.arg1 = id; - msg.arg2 = verified ? 1 : 0; - msg.obj = message; + msg.obj = response; mHandler.sendMessage(msg); } + private ComponentName matchComponentForVerifier(String packageName, + List<ResolveInfo> receivers) { + ActivityInfo targetReceiver = null; + + final int NR = receivers.size(); + for (int i = 0; i < NR; i++) { + final ResolveInfo info = receivers.get(i); + if (info.activityInfo == null) { + continue; + } + + if (packageName.equals(info.activityInfo.packageName)) { + targetReceiver = info.activityInfo; + break; + } + } + + if (targetReceiver == null) { + return null; + } + + return new ComponentName(targetReceiver.packageName, targetReceiver.name); + } + + private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo, + List<ResolveInfo> receivers, final PackageVerificationState verificationState) { + if (pkgInfo.verifiers.length == 0) { + return null; + } + + final int N = pkgInfo.verifiers.length; + final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1); + for (int i = 0; i < N; i++) { + final VerifierInfo verifierInfo = pkgInfo.verifiers[i]; + + final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName, + receivers); + if (comp == null) { + continue; + } + + final int verifierUid = getUidForVerifier(verifierInfo); + if (verifierUid == -1) { + continue; + } + + if (DEBUG_VERIFY) { + Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName + + " with the correct signature"); + } + sufficientVerifiers.add(comp); + verificationState.addSufficientVerifier(verifierUid); + } + + return sufficientVerifiers; + } + + private int getUidForVerifier(VerifierInfo verifierInfo) { + synchronized (mPackages) { + final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName); + if (pkg == null) { + return -1; + } else if (pkg.mSignatures.length != 1) { + Slog.i(TAG, "Verifier package " + verifierInfo.packageName + + " has more than one signature; ignoring"); + return -1; + } + + /* + * If the public key of the package's signature does not match + * our expected public key, then this is a different package and + * we should skip. + */ + + final byte[] expectedPublicKey; + try { + final Signature verifierSig = pkg.mSignatures[0]; + final PublicKey publicKey = verifierSig.getPublicKey(); + expectedPublicKey = publicKey.getEncoded(); + } catch (CertificateException e) { + return -1; + } + + final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded(); + + if (!Arrays.equals(actualPublicKey, expectedPublicKey)) { + Slog.i(TAG, "Verifier package " + verifierInfo.packageName + + " does not have the expected public key; ignoring"); + return -1; + } + + return pkg.applicationInfo.uid; + } + } + public void finishPackageInstall(int token) { enforceSystemOrRoot("Only the system is allowed to finish installs"); @@ -5230,9 +5386,11 @@ public class PackageManagerService extends IPackageManager.Stub { */ public void handleStartCopy() throws RemoteException { int ret = PackageManager.INSTALL_SUCCEEDED; - boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; - boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0; - boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0; + final boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; + final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0; + final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0; + PackageInfoLite pkgLite = null; + if (onInt && onSd) { // Check if both bits are set. Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); @@ -5254,7 +5412,6 @@ public class PackageManagerService extends IPackageManager.Stub { } // Remote call to find out default install location - final PackageInfoLite pkgLite; try { mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); @@ -5297,21 +5454,27 @@ public class PackageManagerService extends IPackageManager.Stub { } final InstallArgs args = createInstallArgs(this); + mArgs = args; + if (ret == PackageManager.INSTALL_SUCCEEDED) { /* * Determine if we have any installed package verifiers. If we * do, then we'll defer to them to verify the packages. */ - final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION, - packageURI); - verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - - final List<ResolveInfo> receivers = queryIntentReceivers(verification, null, - PackageManager.GET_DISABLED_COMPONENTS); - if (isVerificationEnabled() && receivers.size() > 0) { - if (DEBUG_INSTALL) { + final int requiredUid = mRequiredVerifierPackage == null ? -1 + : getPackageUid(mRequiredVerifierPackage); + if (requiredUid != -1 && isVerificationEnabled()) { + final Intent verification = new Intent( + Intent.ACTION_PACKAGE_NEEDS_VERIFICATION, packageURI); + verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + final List<ResolveInfo> receivers = queryIntentReceivers(verification, null, + PackageManager.GET_DISABLED_COMPONENTS); + + if (DEBUG_VERIFY) { Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent " - + verification.toString()); + + verification.toString() + " with " + pkgLite.verifiers.length + + " optional verifiers"); } final int verificationId = mPendingVerificationToken++; @@ -5328,35 +5491,70 @@ public class PackageManagerService extends IPackageManager.Stub { verificationURI); } - mPendingVerification.append(verificationId, args); + final PackageVerificationState verificationState = new PackageVerificationState( + requiredUid, args); + + mPendingVerification.append(verificationId, verificationState); + + final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite, + receivers, verificationState); /* - * Send the intent to the registered verification agents, - * but only start the verification timeout after the target - * BroadcastReceivers have run. + * If any sufficient verifiers were listed in the package + * manifest, attempt to ask them. */ - mContext.sendOrderedBroadcast(verification, - android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final Message msg = mHandler - .obtainMessage(CHECK_PENDING_VERIFICATION); - msg.arg1 = verificationId; - mHandler.sendMessageDelayed(msg, getVerificationTimeout()); - } - }, - null, 0, null, null); + if (sufficientVerifiers != null) { + final int N = sufficientVerifiers.size(); + if (N == 0) { + Slog.i(TAG, "Additional verifiers required, but none installed."); + ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE; + } else { + for (int i = 0; i < N; i++) { + final ComponentName verifierComponent = sufficientVerifiers.get(i); + + final Intent sufficientIntent = new Intent(verification); + sufficientIntent.setComponent(verifierComponent); + + mContext.sendBroadcast(sufficientIntent); + } + } + } + + final ComponentName requiredVerifierComponent = matchComponentForVerifier( + mRequiredVerifierPackage, receivers); + if (ret == PackageManager.INSTALL_SUCCEEDED + && mRequiredVerifierPackage != null) { + /* + * Send the intent to the required verification agent, + * but only start the verification timeout after the + * target BroadcastReceivers have run. + */ + verification.setComponent(requiredVerifierComponent); + mContext.sendOrderedBroadcast(verification, + android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final Message msg = mHandler + .obtainMessage(CHECK_PENDING_VERIFICATION); + msg.arg1 = verificationId; + mHandler.sendMessageDelayed(msg, getVerificationTimeout()); + } + }, null, 0, null, null); + + /* + * We don't want the copy to proceed until verification + * succeeds, so null out this field. + */ + mArgs = null; + } } else { - // Create copy only if we are not in an erroneous state. - // Remote call to initiate copy using temporary file - mArgs = args; + /* + * No package verification is enabled, so immediately start + * the remote call to initiate copy using temporary file. + */ ret = args.copyApk(mContainerService, true); } - } else { - // There was an error, so let the processPendingInstall() break - // the bad news... uh, through a call in handleReturnCode() - mArgs = args; } mRet = ret; @@ -7542,6 +7740,8 @@ public class PackageManagerService extends IPackageManager.Stub { public static final int DUMP_PROVIDERS = 1 << 7; + public static final int DUMP_VERIFIERS = 1 << 8; + public static final int OPTION_SHOW_FILTERS = 1 << 0; private int mTypes; @@ -7634,6 +7834,7 @@ public class PackageManagerService extends IPackageManager.Stub { pw.println(" p[ackages]: dump installed packages"); pw.println(" s[hared-users]: dump shared user IDs"); pw.println(" m[essages]: print collected runtime messages"); + pw.println(" v[erifiers]: print package verifier info"); pw.println(" <package.name>: info about given package"); return; } else if ("-f".equals(opt)) { @@ -7666,11 +7867,24 @@ public class PackageManagerService extends IPackageManager.Stub { dumpState.setDump(DumpState.DUMP_PROVIDERS); } else if ("m".equals(cmd) || "messages".equals(cmd)) { dumpState.setDump(DumpState.DUMP_MESSAGES); + } else if ("v".equals(cmd) || "verifiers".equals(cmd)) { + dumpState.setDump(DumpState.DUMP_VERIFIERS); } } // reader synchronized (mPackages) { + if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) { + if (dumpState.onTitlePrinted()) + pw.println(" "); + pw.println("Verifiers:"); + pw.print(" Required: "); + pw.print(mRequiredVerifierPackage); + pw.print(" (uid="); + pw.print(getPackageUid(mRequiredVerifierPackage)); + pw.println(")"); + } + if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) { if (dumpState.onTitlePrinted()) pw.println(" "); diff --git a/services/java/com/android/server/pm/PackageVerificationResponse.java b/services/java/com/android/server/pm/PackageVerificationResponse.java new file mode 100644 index 000000000000..b2ae0dd433da --- /dev/null +++ b/services/java/com/android/server/pm/PackageVerificationResponse.java @@ -0,0 +1,28 @@ +/* + * 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.server.pm; + +public class PackageVerificationResponse { + public final int code; + + public final int callerUid; + + public PackageVerificationResponse(int code, int callerUid) { + this.code = code; + this.callerUid = callerUid; + } +} diff --git a/services/java/com/android/server/pm/PackageVerificationState.java b/services/java/com/android/server/pm/PackageVerificationState.java new file mode 100644 index 000000000000..e5b89c1f08fe --- /dev/null +++ b/services/java/com/android/server/pm/PackageVerificationState.java @@ -0,0 +1,149 @@ +/* + * 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.server.pm; + +import com.android.server.pm.PackageManagerService.InstallArgs; + +import android.content.pm.PackageManager; +import android.util.SparseBooleanArray; + +/** + * Tracks the package verification state for a particular package. Each package + * verification has a required verifier and zero or more sufficient verifiers. + * Only one of the sufficient verifier list must return affirmative to allow the + * package to be considered verified. If there are zero sufficient verifiers, + * then package verification is considered complete. + */ +class PackageVerificationState { + private final InstallArgs mArgs; + + private final SparseBooleanArray mSufficientVerifierUids; + + private final int mRequiredVerifierUid; + + private boolean mSufficientVerificationComplete; + + private boolean mSufficientVerificationPassed; + + private boolean mRequiredVerificationComplete; + + private boolean mRequiredVerificationPassed; + + /** + * Create a new package verification state where {@code requiredVerifierUid} + * is the user ID for the package that must reply affirmative before things + * can continue. + * + * @param requiredVerifierUid user ID of required package verifier + * @param args + */ + public PackageVerificationState(int requiredVerifierUid, InstallArgs args) { + mRequiredVerifierUid = requiredVerifierUid; + mArgs = args; + mSufficientVerifierUids = new SparseBooleanArray(); + } + + public InstallArgs getInstallArgs() { + return mArgs; + } + + /** + * Add a verifier which is added to our sufficient list. + * + * @param uid user ID of sufficient verifier + */ + public void addSufficientVerifier(int uid) { + mSufficientVerifierUids.put(uid, true); + } + + /** + * Should be called when a verification is received from an agent so the + * state of the package verification can be tracked. + * + * @param uid user ID of the verifying agent + * @return {@code true} if the verifying agent actually exists in our list + */ + public boolean setVerifierResponse(int uid, int code) { + if (uid == mRequiredVerifierUid) { + mRequiredVerificationComplete = true; + switch (code) { + case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT: + mSufficientVerifierUids.clear(); + // fall through + case PackageManager.VERIFICATION_ALLOW: + mRequiredVerificationPassed = true; + break; + default: + mRequiredVerificationPassed = false; + } + return true; + } else { + if (mSufficientVerifierUids.get(uid)) { + if (code == PackageManager.VERIFICATION_ALLOW) { + mSufficientVerificationComplete = true; + mSufficientVerificationPassed = true; + } + + mSufficientVerifierUids.delete(uid); + if (mSufficientVerifierUids.size() == 0) { + mSufficientVerificationComplete = true; + } + + return true; + } + } + + return false; + } + + /** + * Returns whether verification is considered complete. This means that the + * required verifier and at least one of the sufficient verifiers has + * returned a positive verification. + * + * @return {@code true} when verification is considered complete + */ + public boolean isVerificationComplete() { + if (!mRequiredVerificationComplete) { + return false; + } + + if (mSufficientVerifierUids.size() == 0) { + return true; + } + + return mSufficientVerificationComplete; + } + + /** + * Returns whether installation should be allowed. This should only be + * called after {@link #isVerificationComplete()} returns {@code true}. + * + * @return {@code true} if installation should be allowed + */ + public boolean isInstallAllowed() { + if (!mRequiredVerificationPassed) { + return false; + } + + if (mSufficientVerificationComplete) { + return mSufficientVerificationPassed; + } + + return true; + } +} diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java index dd440bf00d1e..f2e7485895fe 100644 --- a/services/java/com/android/server/wm/DragState.java +++ b/services/java/com/android/server/wm/DragState.java @@ -125,6 +125,12 @@ class DragState { mDragWindowHandle.frameTop = 0; mDragWindowHandle.frameRight = mService.mCurDisplayWidth; mDragWindowHandle.frameBottom = mService.mCurDisplayHeight; + + // Pause rotations before a drag. + if (WindowManagerService.DEBUG_ORIENTATION) { + Slog.d(WindowManagerService.TAG, "Pausing rotation during drag"); + } + mService.pauseRotationLocked(); } } @@ -142,6 +148,12 @@ class DragState { mDragWindowHandle = null; mDragApplicationHandle = null; + + // Resume rotations after a drag. + if (WindowManagerService.DEBUG_ORIENTATION) { + Slog.d(WindowManagerService.TAG, "Resuming rotation after drag"); + } + mService.resumeRotationLocked(); } } @@ -257,13 +269,6 @@ class DragState { // free our resources and drop all the object references mService.mDragState.reset(); mService.mDragState = null; - - if (WindowManagerService.DEBUG_ORIENTATION) Slog.d(WindowManagerService.TAG, "Performing post-drag rotation"); - boolean changed = mService.setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); - if (changed) { - mService.mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } } void notifyMoveLw(float x, float y) { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index ff75cfda118d..3ea9e817a1d8 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -427,14 +427,11 @@ public class WindowManagerService extends IWindowManager.Stub int mAppDisplayWidth = 0; int mAppDisplayHeight = 0; int mRotation = 0; - int mRequestedRotation = 0; int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; boolean mAltOrientation = false; - int mLastRotationFlags; ArrayList<IRotationWatcher> mRotationWatchers = new ArrayList<IRotationWatcher>(); - int mDeferredRotation; - int mDeferredRotationAnimFlags; + int mDeferredRotationPauseCount; boolean mLayoutNeeded = true; boolean mAnimationPending = false; @@ -3414,9 +3411,7 @@ public class WindowManagerService extends IWindowManager.Stub //send a message to Policy indicating orientation change to take //action like disabling/enabling sensors etc., mPolicy.setCurrentOrientationLw(req); - if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION, - mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE, - inTransaction)) { + if (updateRotationUncheckedLocked(inTransaction)) { changed = true; } } @@ -4530,6 +4525,16 @@ public class WindowManagerService extends IWindowManager.Stub return mPolicy.isKeyguardSecure(); } + public void dismissKeyguard() { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires DISABLE_KEYGUARD permission"); + } + synchronized(mWindowMap) { + mPolicy.dismissKeyguardLw(); + } + } + public void closeSystemDialogs(String reason) { synchronized(mWindowMap) { for (int i=mWindows.size()-1; i>=0; i--) { @@ -4823,8 +4828,7 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.enableScreenAfterBoot(); // Make sure the last requested orientation has been applied. - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, - mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateRotationUnchecked(false); } public void showBootMessage(final CharSequence msg, final boolean always) { @@ -5043,6 +5047,10 @@ public class WindowManagerService extends IWindowManager.Stub return bm; } + /** + * Freeze rotation changes. (Enable "rotation lock".) + * Persists across reboots. + */ public void freezeRotation() { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, "freezeRotation()")) { @@ -5052,9 +5060,13 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mRotation); - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); + updateRotationUnchecked(false); } + /** + * Thaw rotation changes. (Disable "rotation lock".) + * Persists across reboots. + */ public void thawRotation() { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, "thawRotation()")) { @@ -5064,30 +5076,56 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); + updateRotationUnchecked(false); } - public void setRotation(int rotation, - boolean alwaysSendConfiguration, int animFlags) { - if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "setRotation()")) { - throw new SecurityException("Requires SET_ORIENTATION permission"); - } + /** + * Recalculate the current rotation. + * + * Called by the window manager policy whenever the state of the system changes + * such that the current rotation might need to be updated, such as when the + * device is docked or rotated into a new posture. + */ + public void updateRotation(boolean alwaysSendConfiguration) { + updateRotationUnchecked(alwaysSendConfiguration); + } - setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags); + /** + * Temporarily pauses rotation changes until resumed. + * + * This can be used to prevent rotation changes from occurring while the user is + * performing certain operations, such as drag and drop. + * + * This call nests and must be matched by an equal number of calls to {@link #resumeRotation}. + */ + void pauseRotationLocked() { + mDeferredRotationPauseCount += 1; } - public void setRotationUnchecked(int rotation, - boolean alwaysSendConfiguration, int animFlags) { - if(DEBUG_ORIENTATION) Slog.v(TAG, - "setRotationUnchecked(rotation=" + rotation + - " alwaysSendConfiguration=" + alwaysSendConfiguration + - " animFlags=" + animFlags); + /** + * Resumes normal rotation changes after being paused. + */ + void resumeRotationLocked() { + if (mDeferredRotationPauseCount > 0) { + mDeferredRotationPauseCount -= 1; + if (mDeferredRotationPauseCount == 0) { + boolean changed = updateRotationUncheckedLocked(false); + if (changed) { + mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); + } + } + } + } + + public void updateRotationUnchecked( + boolean alwaysSendConfiguration) { + if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" + + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); long origId = Binder.clearCallingIdentity(); boolean changed; synchronized(mWindowMap) { - changed = setRotationUncheckedLocked(rotation, animFlags, false); + changed = updateRotationUncheckedLocked(false); } if (changed || alwaysSendConfiguration) { @@ -5098,152 +5136,114 @@ public class WindowManagerService extends IWindowManager.Stub } /** - * Apply a new rotation to the screen, respecting the requests of - * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply - * re-evaluate the desired rotation. - * - * Returns null if the rotation has been changed. In this case YOU - * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN. + * Updates the current rotation. + * + * Returns true if the rotation has been changed. In this case YOU + * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. */ - public boolean setRotationUncheckedLocked(int rotation, int animFlags, boolean inTransaction) { - if (mDragState != null - || (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating())) { - // Potential rotation during a drag or while waiting for a previous orientation - // change to finish (rotation animation will be dismissed). - // Don't do the rotation now, but make a note to perform the rotation later. - if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation."); - if (rotation != WindowManagerPolicy.USE_LAST_ROTATION) { - mDeferredRotation = rotation; - mDeferredRotationAnimFlags = animFlags; - } + public boolean updateRotationUncheckedLocked(boolean inTransaction) { + if (mDeferredRotationPauseCount > 0) { + // Rotation updates have been paused temporarily. Defer the update until + // updates have been resumed. + if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); return false; } - boolean changed; - if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) { - if (mDeferredRotation != WindowManagerPolicy.USE_LAST_ROTATION) { - rotation = mDeferredRotation; - mRequestedRotation = rotation; - mLastRotationFlags = mDeferredRotationAnimFlags; - } - rotation = mRequestedRotation; - } else { - mRequestedRotation = rotation; - mLastRotationFlags = animFlags; - } - mDeferredRotation = WindowManagerPolicy.USE_LAST_ROTATION; - if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation); - rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, - mRotation, mDisplayEnabled); - if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation); - - int desiredRotation = rotation; - int lockedRotation = mPolicy.getLockedRotationLw(); - if (lockedRotation >= 0 && rotation != lockedRotation) { - // We are locked in a rotation but something is requesting - // a different rotation... we will either keep the locked - // rotation if it results in the same orientation, or have to - // switch into an emulated orientation mode. - - // First, we know that our rotation is actually going to be - // the locked rotation. - rotation = lockedRotation; - - // Now the difference between the desired and lockedRotation - // may mean that the orientation is different... if that is - // not the case, we can just make the desired rotation be the - // same as the new locked rotation. - switch (lockedRotation) { - case Surface.ROTATION_0: - if (rotation == Surface.ROTATION_180) { - desiredRotation = lockedRotation; - } - break; - case Surface.ROTATION_90: - if (rotation == Surface.ROTATION_270) { - desiredRotation = lockedRotation; - } - break; - case Surface.ROTATION_180: - if (rotation == Surface.ROTATION_0) { - desiredRotation = lockedRotation; - } - break; - case Surface.ROTATION_270: - if (rotation == Surface.ROTATION_90) { - desiredRotation = lockedRotation; - } - break; - } + if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) { + // Rotation updates cannot be performed while the previous rotation change + // animation is still in progress. Skip this update. We will try updating + // again after the animation is finished and the display is unfrozen. + if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); + return false; } - changed = mDisplayEnabled && mRotation != rotation; - if (mAltOrientation != (rotation != desiredRotation)) { - changed = true; - mAltOrientation = rotation != desiredRotation; + if (!mDisplayEnabled) { + // No point choosing a rotation if the display is not enabled. + if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); + return false; } - if (changed) { - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Rotation changed to " + rotation - + " from " + mRotation - + " (forceApp=" + mForcedAppOrientation - + ", req=" + mRequestedRotation + ")"); - mRotation = rotation; - mWindowsFreezingScreen = true; - mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); - mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), - 2000); - mWaitingForConfig = true; - mLayoutNeeded = true; - startFreezingDisplayLocked(inTransaction); - //Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags); - mInputManager.setDisplayOrientation(0, rotation); - if (mDisplayEnabled) { - // NOTE: We disable the rotation in the emulator because - // it doesn't support hardware OpenGL emulation yet. - if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null - && mScreenRotationAnimation.hasScreenshot()) { - Surface.freezeDisplay(0); - if (!inTransaction) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, - ">>> OPEN TRANSACTION setRotationUnchecked"); - Surface.openTransaction(); - } - try { - if (mScreenRotationAnimation != null) { - mScreenRotationAnimation.setRotation(rotation); - } - } finally { - if (!inTransaction) { - Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, - "<<< CLOSE TRANSACTION setRotationUnchecked"); - } - } - Surface.setOrientation(0, rotation, animFlags); - Surface.unfreezeDisplay(0); - } else { - Surface.setOrientation(0, rotation, animFlags); - } - rebuildBlackFrame(inTransaction); - } + // TODO: Implement forced rotation changes. + // Set mAltOrientation to indicate that the application is receiving + // an orientation that has different metrics than it expected. + // eg. Portrait instead of Landscape. - for (int i=mWindows.size()-1; i>=0; i--) { - WindowState w = mWindows.get(i); - if (w.mSurface != null) { - w.mOrientationChanging = true; - } + int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); + boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( + mForcedAppOrientation, rotation); + + if (DEBUG_ORIENTATION) { + Slog.v(TAG, "Application requested orientation " + + mForcedAppOrientation + ", got rotation " + rotation + + " which has " + (altOrientation ? "incompatible" : "compatible") + + " metrics"); + } + + if (mRotation == rotation && mAltOrientation == altOrientation) { + // No change. + return false; + } + + if (DEBUG_ORIENTATION) { + Slog.v(TAG, + "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") + + " from " + mRotation + (mAltOrientation ? " (alt)" : "") + + ", forceApp=" + mForcedAppOrientation); + } + + mRotation = rotation; + mAltOrientation = altOrientation; + mPolicy.setRotationLw(mRotation); + + mWindowsFreezingScreen = true; + mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); + mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000); + mWaitingForConfig = true; + mLayoutNeeded = true; + startFreezingDisplayLocked(inTransaction); + mInputManager.setDisplayOrientation(0, rotation); + + // NOTE: We disable the rotation in the emulator because + // it doesn't support hardware OpenGL emulation yet. + if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null + && mScreenRotationAnimation.hasScreenshot()) { + Surface.freezeDisplay(0); + if (!inTransaction) { + if (SHOW_TRANSACTIONS) Slog.i(TAG, + ">>> OPEN TRANSACTION setRotationUnchecked"); + Surface.openTransaction(); } - for (int i=mRotationWatchers.size()-1; i>=0; i--) { - try { - mRotationWatchers.get(i).onRotationChanged(rotation); - } catch (RemoteException e) { + try { + if (mScreenRotationAnimation != null) { + mScreenRotationAnimation.setRotation(rotation); + } + } finally { + if (!inTransaction) { + Surface.closeTransaction(); + if (SHOW_TRANSACTIONS) Slog.i(TAG, + "<<< CLOSE TRANSACTION setRotationUnchecked"); } } - } //end if changed + Surface.setOrientation(0, rotation); + Surface.unfreezeDisplay(0); + } else { + Surface.setOrientation(0, rotation); + } + rebuildBlackFrame(inTransaction); - return changed; + for (int i=mWindows.size()-1; i>=0; i--) { + WindowState w = mWindows.get(i); + if (w.mSurface != null) { + w.mOrientationChanging = true; + } + } + for (int i=mRotationWatchers.size()-1; i>=0; i--) { + try { + mRotationWatchers.get(i).onRotationChanged(rotation); + } catch (RemoteException e) { + } + } + return true; } public int getRotation() { @@ -8601,8 +8601,7 @@ public class WindowManagerService extends IWindowManager.Stub if (updateRotation) { if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); - boolean changed = setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); + boolean changed = updateRotationUncheckedLocked(false); if (changed) { mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); } else { @@ -9029,8 +9028,7 @@ public class WindowManagerService extends IWindowManager.Stub if (updateRotation) { if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); - configChanged |= setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); + configChanged |= updateRotationUncheckedLocked(false); } if (configChanged) { @@ -9403,12 +9401,10 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); pw.print(" mRotation="); pw.print(mRotation); - pw.print(" mRequestedRotation="); pw.print(mRequestedRotation); pw.print(" mAltOrientation="); pw.println(mAltOrientation); pw.print(" mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation); pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); - pw.print(" mDeferredRotation="); pw.print(mDeferredRotation); - pw.print(", mDeferredRotationAnimFlags="); pw.println(mDeferredRotationAnimFlags); + pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); pw.print(" mAnimationPending="); pw.print(mAnimationPending); pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale); diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 455d6649bb4a..3640a15284b2 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -636,7 +636,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { final boolean isHwAccelerated = (mAttrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format; - if (isHwAccelerated && mAttrs.format == PixelFormat.OPAQUE) { + if (!PixelFormat.formatHasAlpha(mAttrs.format)) { flags |= Surface.OPAQUE; } mSurface = new Surface( diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index e707bdce7ddc..879e858027fb 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -176,9 +176,9 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE, mList->numHwLayers, mList->flags); result.append(buffer); result.append( - " type | hints | flags | tr | blend | format | source rectangle | crop rectangle name \n" - "-----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); - // " ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] + " type | handle | hints | flags | tr | blend | format | source crop | frame name \n" + "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); + // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] for (size_t i=0 ; i<mList->numHwLayers ; i++) { const hwc_layer_t& l(mList->hwLayers[i]); const sp<LayerBase> layer(visibleLayersSortedByZ[i]); @@ -190,9 +190,9 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE, } } snprintf(buffer, SIZE, - " %8s | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", + " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", l.compositionType ? "OVERLAY" : "FB", - l.hints, l.flags, l.transform, l.blending, format, + intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format, l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, layer->getName().string()); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f85ce7fd0949..41d7a90978ad 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -112,6 +112,11 @@ void Layer::onRemoved() mSurfaceTexture->abandon(); } +void Layer::setName(const String8& name) { + LayerBase::setName(name); + mSurfaceTexture->setName(name); +} + sp<ISurface> Layer::createSurface() { class BSurface : public BnSurface, public LayerCleaner { @@ -371,11 +376,12 @@ uint32_t Layer::doTransaction(uint32_t flags) Layer::State& editDraw(mDrawingState); editDraw.requested_w = temp.requested_w; editDraw.requested_h = temp.requested_h; - - // record the new size, form this point on, when the client request - // a buffer, it'll get the new size. - mSurfaceTexture->setDefaultBufferSize(temp.requested_w, temp.requested_h); } + + // record the new size, form this point on, when the client request + // a buffer, it'll get the new size. + mSurfaceTexture->setDefaultBufferSize(temp.requested_w, + temp.requested_h); } if (temp.sequence != front.sequence) { @@ -578,7 +584,7 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const uint32_t Layer::getTransformHint() const { uint32_t orientation = 0; if (!mFlinger->mDebugDisableTransformHint) { - orientation = getOrientation(); + orientation = getPlaneOrientation(); if (orientation & Transform::ROT_INVALID) { orientation = 0; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ff389aecef70..82e35218d279 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -74,6 +74,7 @@ public: virtual bool isProtected() const; virtual void onRemoved(); virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); } + virtual void setName(const String8& name); // LayerBaseClient interface virtual wp<IBinder> getSurfaceTextureBinder() const; diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index e5ce814bda33..7a47f620f392 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -45,6 +45,7 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) mFlinger(flinger), mFiltering(false), mNeedsFiltering(false), mInOverlay(false), mOrientation(0), + mPlaneOrientation(0), mTransactionFlags(0), mPremultipliedAlpha(true), mName("unnamed"), mDebug(false), mInvalidate(0) @@ -256,6 +257,7 @@ void LayerBase::validateVisibility(const Transform& planeTransform) // cache a few things... mOrientation = tr.getOrientation(); + mPlaneOrientation = planeTransform.getOrientation(); mTransform = tr; mTransformedBounds = tr.makeBounds(w, h); } diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index a14b397a8d42..7f6214510d33 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -81,7 +81,7 @@ public: Region transparentRegion; }; - void setName(const String8& name); + virtual void setName(const String8& name); String8 getName() const; // modify current state @@ -221,6 +221,7 @@ public: inline State& currentState() { return mCurrentState; } int32_t getOrientation() const { return mOrientation; } + int32_t getPlaneOrientation() const { return mPlaneOrientation; } protected: const GraphicPlane& graphicPlane(int dpy) const; @@ -254,6 +255,7 @@ private: protected: // cached during validateVisibility() int32_t mOrientation; + int32_t mPlaneOrientation; Transform mTransform; GLfloat mVertices[4][2]; Rect mTransformedBounds; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0ef03bb7dde8..3f154ce3292d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -566,7 +566,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const int dpy = 0; const int orientation = mCurrentState.orientation; - const uint32_t type = mCurrentState.orientationType; + // Currently unused: const uint32_t flags = mCurrentState.orientationFlags; GraphicPlane& plane(graphicPlane(dpy)); plane.setOrientation(orientation); @@ -986,19 +986,20 @@ void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut) void SurfaceFlinger::composeSurfaces(const Region& dirty) { - if (UNLIKELY(!mWormholeRegion.isEmpty())) { + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + HWComposer& hwc(hw.getHwComposer()); + + const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER); + if (UNLIKELY(fbLayerCount && !mWormholeRegion.isEmpty())) { // should never happen unless the window manager has a bug // draw something... drawWormhole(); } - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - HWComposer& hwc(hw.getHwComposer()); - hwc_layer_t* const cur(hwc.getLayers()); - /* * and then, render the layers targeted at the framebuffer */ + hwc_layer_t* const cur(hwc.getLayers()); const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { @@ -1299,7 +1300,7 @@ int SurfaceFlinger::setOrientation(DisplayID dpy, Mutex::Autolock _l(mStateLock); if (mCurrentState.orientation != orientation) { if (uint32_t(orientation)<=eOrientation270 || orientation==42) { - mCurrentState.orientationType = flags; + mCurrentState.orientationFlags = flags; mCurrentState.orientation = orientation; setTransactionFlags(eTransactionNeeded); mTransactionCV.wait(mStateLock); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d7f005f7cefe..43191b7e8a54 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -245,7 +245,7 @@ private: } LayerVector layersSortedByZ; uint8_t orientation; - uint8_t orientationType; + uint8_t orientationFlags; uint8_t freezeDisplay; }; diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index 99ae027f4b16..2ead254af18c 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -776,6 +776,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { private void expectNetworkStatsPoll() throws Exception { mNetManager.setGlobalAlert(anyLong()); expectLastCall().anyTimes(); + expect(mConnManager.getTetheredIfacePairs()).andReturn(null).anyTimes(); } private void assertStatsFilesExist(boolean exist) { diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java new file mode 100644 index 000000000000..ebd363386fa3 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java @@ -0,0 +1,205 @@ +/* + * 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.server.pm; + +import android.content.pm.PackageManager; +import com.android.server.pm.PackageVerificationState; + +import android.test.AndroidTestCase; + +public class PackageVerificationStateTest extends AndroidTestCase { + private static final int REQUIRED_UID = 1948; + + private static final int SUFFICIENT_UID_1 = 1005; + + private static final int SUFFICIENT_UID_2 = 8938; + + public void testPackageVerificationState_OnlyRequiredVerifier_AllowedInstall() { + PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW); + + assertTrue("Verification should be considered complete now", + state.isVerificationComplete()); + + assertTrue("Installation should be marked as allowed", + state.isInstallAllowed()); + } + + public void testPackageVerificationState_OnlyRequiredVerifier_DeniedInstall() { + PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT); + + assertTrue("Verification should be considered complete now", + state.isVerificationComplete()); + + assertFalse("Installation should be marked as allowed", + state.isInstallAllowed()); + } + + public void testPackageVerificationState_RequiredAndOneSufficient_RequiredDeniedInstall() { + PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.addSufficientVerifier(SUFFICIENT_UID_1); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_ALLOW); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT); + + assertTrue("Verification should be considered complete now", + state.isVerificationComplete()); + + assertFalse("Installation should be marked as allowed", + state.isInstallAllowed()); + } + + public void testPackageVerificationState_RequiredAndOneSufficient_SufficientDeniedInstall() { + PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.addSufficientVerifier(SUFFICIENT_UID_1); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_REJECT); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW); + + assertTrue("Verification should be considered complete now", + state.isVerificationComplete()); + + assertFalse("Installation should be marked as allowed", + state.isInstallAllowed()); + } + + public void testPackageVerificationState_RequiredAndTwoSufficient_OneSufficientIsEnough() { + PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.addSufficientVerifier(SUFFICIENT_UID_1); + state.addSufficientVerifier(SUFFICIENT_UID_2); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_ALLOW); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW); + + assertTrue("Verification should be considered complete now", + state.isVerificationComplete()); + + assertTrue("Installation should be marked as allowed", + state.isInstallAllowed()); + } + + public void testPackageVerificationState_RequiredAndTwoSufficient_SecondSufficientIsEnough() { + PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.addSufficientVerifier(SUFFICIENT_UID_1); + state.addSufficientVerifier(SUFFICIENT_UID_2); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_REJECT); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(SUFFICIENT_UID_2, PackageManager.VERIFICATION_ALLOW); + + assertTrue("Verification should be considered complete now", + state.isVerificationComplete()); + + assertTrue("Installation should be marked as allowed", + state.isInstallAllowed()); + } + + public void testPackageVerificationState_RequiredAndTwoSufficient_RequiredOverrides() { + PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.addSufficientVerifier(SUFFICIENT_UID_1); + state.addSufficientVerifier(SUFFICIENT_UID_2); + + assertFalse("Verification should not be marked as complete yet", + state.isVerificationComplete()); + + state.setVerifierResponse(REQUIRED_UID, + PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT); + + assertTrue("Verification should be marked as complete immediately", + state.isVerificationComplete()); + + assertTrue("Installation should be marked as allowed", + state.isInstallAllowed()); + + state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_REJECT); + + assertTrue("Verification should still be marked as completed", + state.isVerificationComplete()); + + assertTrue("Installation should be marked as allowed still", + state.isInstallAllowed()); + + state.setVerifierResponse(SUFFICIENT_UID_2, PackageManager.VERIFICATION_ALLOW); + + assertTrue("Verification should still be complete", + state.isVerificationComplete()); + + assertTrue("Installation should be marked as allowed still", + state.isInstallAllowed()); + } +} diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 3e8d25558fe8..34f88489ed6a 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1409,6 +1409,11 @@ public class PhoneNumberUtils * @hide */ public static String formatNumber(String phoneNumber, String defaultCountryIso) { + // Do not attempt to format numbers that start with a hash or star symbol. + if (phoneNumber.startsWith("#") || phoneNumber.startsWith("*")) { + return phoneNumber; + } + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); String result = null; try { @@ -1567,6 +1572,14 @@ public class PhoneNumberUtils // that has been collected. if (util.isValidNumber(pn)) { return false; + } else if ("BR".equalsIgnoreCase(defaultCountryIso) && number.length() >= 8) { + // This is to prevent Brazilian local numbers which start with 911 being incorrectly + // classified as emergency numbers. 911 is not an emergency number in Brazil; it is also + // not possible to append additional digits to an emergency number to dial the number in + // Brazil - it won't connect. + // TODO: Clean this up once a list of country-specific known emergency numbers is + // collected. + return false; } } catch (NumberParseException e) { } diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 101dd55e4a79..abb45234dc8e 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -182,9 +182,4 @@ public interface TelephonyProperties * in commercial configuration. */ static final String PROPERTY_TEST_CSIM = "persist.radio.test-csim"; - - /** - * Set to true to indicate a test ims registration required. - */ - static final String PROPERTY_IMS_REG_REQUIRED = "persist.radio.imsregrequired"; } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index ebf5e65a3d9d..78ba7ddd0ba9 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -1768,8 +1768,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { ApnSetting apn = apnContext.getApnSetting(); if (apn.proxy != null && apn.proxy.length() != 0) { try { + String port = apn.port; + if (TextUtils.isEmpty(port)) port = "8080"; ProxyProperties proxy = new ProxyProperties(apn.proxy, - Integer.parseInt(apn.port), null); + Integer.parseInt(port), null); dcac.setLinkPropertiesHttpProxySync(proxy); } catch (NumberFormatException e) { loge("onDataSetupComplete: NumberFormatException making ProxyProperties (" + @@ -2085,18 +2087,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } /** - * Check current radio access technology is LTE or EHRPD. - * - * @param integer value of radio access technology - * @return true when current radio access technology is LTE or EHRPD - * @ false when current radio access technology is not LTE or EHRPD - */ - private boolean needToCheckApnBearer(int radioTech) { - return (radioTech == ServiceState.RADIO_TECHNOLOGY_LTE || - radioTech == ServiceState.RADIO_TECHNOLOGY_EHRPD); - } - - /** * Build a list of APNs to be used to create PDP's. * * @param requestedApnType @@ -2117,7 +2107,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { String operator = mPhone.mIccRecords.getOperatorNumeric(); int radioTech = mPhone.getServiceState().getRadioTechnology(); - boolean needToCheckApnBearer = needToCheckApnBearer(radioTech); if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { if (canSetPreferApn && mPreferredApn != null) { @@ -2126,7 +2115,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { + mPreferredApn.numeric + ":" + mPreferredApn); } if (mPreferredApn.numeric.equals(operator)) { - if (!needToCheckApnBearer || mPreferredApn.bearer == radioTech) { + if (mPreferredApn.bearer == 0 || mPreferredApn.bearer == radioTech) { apnList.add(mPreferredApn); if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList); return apnList; @@ -2145,7 +2134,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (mAllApns != null) { for (ApnSetting apn : mAllApns) { if (apn.canHandleType(requestedApnType)) { - if (!needToCheckApnBearer || apn.bearer == radioTech) { + if (apn.bearer == 0 || apn.bearer == radioTech) { if (DBG) log("apn info : " +apn.toString()); apnList.add(apn); } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java index d3e4b78fde9d..e2349afbf85e 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java @@ -513,7 +513,19 @@ public class PhoneNumberUtilsTest extends AndroidTestCase { assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "US")); assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "US")); assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "US")); + } + @SmallTest + public void testFormatNumber_LeadingStarAndHash() { + // Numbers with a leading '*' or '#' should be left unchanged. + assertEquals("*650 2910000", PhoneNumberUtils.formatNumber("*650 2910000", "US")); + assertEquals("#650 2910000", PhoneNumberUtils.formatNumber("#650 2910000", "US")); + assertEquals("*#650 2910000", PhoneNumberUtils.formatNumber("*#650 2910000", "US")); + assertEquals("#*650 2910000", PhoneNumberUtils.formatNumber("#*650 2910000", "US")); + assertEquals("#650*2910000", PhoneNumberUtils.formatNumber("#650*2910000", "US")); + assertEquals("#650*2910000", PhoneNumberUtils.formatNumber("#650*2910000", "US")); + assertEquals("##650 2910000", PhoneNumberUtils.formatNumber("##650 2910000", "US")); + assertEquals("**650 2910000", PhoneNumberUtils.formatNumber("**650 2910000", "US")); } @SmallTest @@ -551,5 +563,8 @@ public class PhoneNumberUtilsTest extends AndroidTestCase { // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number // in Brazil, as 112 is not an emergency number there. assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR")); + // A valid local phone number from Brazil shouldn't be classified as an emergency number in + // Brazil. + assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "BR")); } } diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index f2fb36f497f9..58680ea5dd49 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -36,9 +36,11 @@ import android.content.pm.PermissionInfo; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.Signature; import android.content.pm.UserInfo; import android.content.pm.ManifestDigest; import android.content.pm.VerifierDeviceIdentity; +import android.content.pm.VerifierInfo; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; @@ -546,11 +548,8 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } - /** - * @hide - */ @Override - public void verifyPendingInstall(int id, boolean verified, String failureMessage) { + public void verifyPendingInstall(int id, int verificationCode) { throw new UnsupportedOperationException(); } diff --git a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java index b803b98253c2..a13c0c978282 100644 --- a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java +++ b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java @@ -89,18 +89,27 @@ public class DataIdleTest extends InstrumentationTestCase { Bundle result = new Bundle(); long rxBytes = 0; long txBytes = 0; + long rxPackets = 0; + long txPackets = 0; for (int i = 0; i < stats.size(); ++i) { // Label will be iface_uid_tag_set Entry statsEntry = stats.getValues(i, null); + // Debugging use. + /* String labelTemplate = String.format("%s_%d_%d_%d", statsEntry.iface, statsEntry.uid, statsEntry.tag, statsEntry.set) + "_%s"; result.putLong(String.format(labelTemplate, "rxBytes"), statsEntry.rxBytes); result.putLong(String.format(labelTemplate, "txBytes"), statsEntry.txBytes); + */ + rxPackets += statsEntry.rxPackets; rxBytes += statsEntry.rxBytes; + txPackets += statsEntry.txPackets; txBytes += statsEntry.txBytes; } - result.putLong("Total rxBytes", rxBytes); - result.putLong("Total txBytes", txBytes); + result.putLong("Total rx Bytes", rxBytes); + result.putLong("Total tx Bytes", txBytes); + result.putLong("Total rx Packets", rxPackets); + result.putLong("Total tx Packets", txPackets); getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, result); } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java index 4ba2e18f01f3..c0ba8cf53254 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java @@ -286,23 +286,11 @@ public class TestShellActivity extends Activity implements LayoutTestController mWebView.stopLoading(); } - - //TODO: remove. this is temporary for bug investigation - @Override - public void finish() { - Exception e = new Exception("finish() call stack"); - Log.d(LOGTAG, "finish stack trace", e); - super.finish(); - } - @Override protected void onDestroy() { - //TODO: remove exception log. this is temporary for bug investigation - Exception e = new Exception("onDestroy stack trace"); - Log.d(LOGTAG, "onDestroy stack trace", e); + super.onDestroy(); mWebView.destroy(); mWebView = null; - super.onDestroy(); } @Override @@ -916,6 +904,9 @@ public class TestShellActivity extends Activity implements LayoutTestController settings.setWorkersEnabled(false); settings.setXSSAuditorEnabled(false); settings.setPageCacheCapacity(0); + // this enables cpu upload path (as opposed to gpu upload path) + // and it's only meant to be a temporary workaround! + settings.setProperty("enable_cpu_upload_path", "true"); } private WebView mWebView; diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index d74d80d0d98a..929b103bc5be 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -31,6 +31,15 @@ android:hardwareAccelerated="true"> <activity + android:name="DisplayListLayersActivity" + android:label="__DisplayListLayers"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="TextFadeActivity" android:label="_TextFade"> <intent-filter> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DisplayListLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DisplayListLayersActivity.java new file mode 100644 index 000000000000..ec91c35dce0f --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DisplayListLayersActivity.java @@ -0,0 +1,125 @@ +/* + * 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.test.hwui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Bundle; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; + +import static android.view.View.LAYER_TYPE_HARDWARE; +import static android.view.View.LAYER_TYPE_SOFTWARE; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +@SuppressWarnings({"UnusedDeclaration"}) +public class DisplayListLayersActivity extends Activity { + private static final int VERTICAL_MARGIN = 12; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + LinearLayout root = createContainer(); + addChild(root, new LayerView(this, 0xffff0000, LAYER_TYPE_HARDWARE, "hardware"), + WRAP_CONTENT, WRAP_CONTENT); + addChild(root, new LayerView(this, 0xff0000ff, LAYER_TYPE_SOFTWARE, "software"), + WRAP_CONTENT, WRAP_CONTENT); + addChild(root, createButton(root), WRAP_CONTENT, WRAP_CONTENT); + + setContentView(root); + } + + private Button createButton(final LinearLayout root) { + Button button = new Button(this); + button.setText("Invalidate"); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + for (int i = 0; i < root.getChildCount(); i++) { + View child = root.getChildAt(i); + if (child != v) { + child.invalidate(); + } + } + } + }); + + return button; + } + + private void addChild(LinearLayout root, View child, int width, int height) { + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, height); + params.gravity = Gravity.CENTER_HORIZONTAL; + params.setMargins(0, dipToPx(VERTICAL_MARGIN), 0, 0); + root.addView(child, params); + } + + private int dipToPx(int size) { + return (int) (getResources().getDisplayMetrics().density * size + 0.5f); + } + + private LinearLayout createContainer() { + LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + return layout; + } + + private class LayerView extends View { + private static final String LOG_TAG = "LayerView"; + private final Paint mPaint = new Paint(); + + private final String mTag; + + LayerView(Context context, int color, int layerType, String tag) { + super(context); + + mTag = tag; + + mPaint.setColor(color); + setLayerType(layerType, null); + } + + private void log(String tag) { + Log.d(LOG_TAG, mTag + ": " + tag); + } + + @Override + public void invalidate() { + log("invalidate"); + super.invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + log("draw"); + canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec) / 3, + MeasureSpec.getSize(heightMeasureSpec) / 3); + } + } +} diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index f015378e2610..5df018e68eaf 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -412,9 +412,31 @@ public class WindowManagerPermissionTests extends TestCase { @SmallTest public void testSET_ORIENTATION() { try { - mWm.setRotation(0, true, 0); + mWm.updateRotation(true); mWm.getSwitchState(0); - fail("IWindowManager.setRotation did not throw SecurityException as" + fail("IWindowManager.updateRotation did not throw SecurityException as" + + " expected"); + } catch (SecurityException e) { + // expected + } catch (RemoteException e) { + fail("Unexpected remote exception"); + } + + try { + mWm.freezeRotation(); + mWm.getSwitchState(0); + fail("IWindowManager.freezeRotation did not throw SecurityException as" + + " expected"); + } catch (SecurityException e) { + // expected + } catch (RemoteException e) { + fail("Unexpected remote exception"); + } + + try { + mWm.thawRotation(); + mWm.getSwitchState(0); + fail("IWindowManager.thawRotation did not throw SecurityException as" + " expected"); } catch (SecurityException e) { // expected diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 178e7fdcffd3..413a2dcf3768 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -368,6 +368,7 @@ enum { REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, + PUBLIC_KEY_ATTR = 0x010103a6, }; const char *getComponentName(String8 &pkgName, String8 &componentName) { @@ -1021,6 +1022,15 @@ int doDump(Bundle* bundle) } else if (tag == "compatible-screens") { printCompatibleScreens(tree); depth--; + } else if (tag == "package-verifier") { + String8 name = getAttribute(tree, NAME_ATTR, &error); + if (name != "" && error == "") { + String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error); + if (publicKey != "" && error == "") { + printf("package-verifier: name='%s' publicKey='%s'\n", + name.string(), publicKey.string()); + } + } } } else if (depth == 3 && withinApplication) { withinActivity = false; diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 81b924af8d7e..99f74c6c10f1 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -695,7 +695,7 @@ status_t parseAndAddEntry(Bundle* bundle, if (isInProductList(product, String16(bundleProduct))) { ; } else if (strcmp16(String16("default").string(), product.string()) == 0 && - !outTable->hasBagOrEntry(myPackage, curType, ident)) { + !outTable->hasBagOrEntry(myPackage, curType, ident, config)) { ; } else { return NO_ERROR; @@ -1823,6 +1823,37 @@ bool ResourceTable::hasBagOrEntry(const String16& package, return false; } +bool ResourceTable::hasBagOrEntry(const String16& package, + const String16& type, + const String16& name, + const ResTable_config& config) const +{ + // First look for this in the included resources... + uint32_t rid = mAssets->getIncludedResources() + .identifierForName(name.string(), name.size(), + type.string(), type.size(), + package.string(), package.size()); + if (rid != 0) { + return true; + } + + sp<Package> p = mPackages.valueFor(package); + if (p != NULL) { + sp<Type> t = p->getTypes().valueFor(type); + if (t != NULL) { + sp<ConfigList> c = t->getConfigs().valueFor(name); + if (c != NULL) { + sp<Entry> e = c->getEntries().valueFor(config); + if (e != NULL) { + return true; + } + } + } + } + + return false; +} + bool ResourceTable::hasBagOrEntry(const String16& ref, const String16* defType, const String16* defPackage) diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index 734c541f9b61..80f2192da4f6 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -124,6 +124,11 @@ public: const String16& type, const String16& name) const; + bool hasBagOrEntry(const String16& package, + const String16& type, + const String16& name, + const ResTable_config& config) const; + bool hasBagOrEntry(const String16& ref, const String16* defType = NULL, const String16* defPackage = NULL); diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java index 973253074640..8868c65e59a8 100644 --- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java +++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java @@ -47,14 +47,14 @@ public class Display_Delegate { @LayoutlibDelegate /** @hide special for when we are faking the screen size. */ - /*package*/ static int getRawWidth(Display theDisplay) { + /*package*/ static int getRawWidthNative(Display theDisplay) { // same as real since we're not faking compatibility mode. return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels; } @LayoutlibDelegate /** @hide special for when we are faking the screen size. */ - /*package*/ static int getRawHeight(Display theDisplay) { + /*package*/ static int getRawHeightNative(Display theDisplay) { // same as real since we're not faking compatibility mode. return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java index 3d1fa7aed622..5b57266b4daa 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java @@ -396,7 +396,7 @@ public class BridgeWindowManager implements IWindowManager { } - public void setRotation(int arg0, boolean arg1, int arg2) throws RemoteException { + public void updateRotation(boolean arg0) throws RemoteException { // TODO Auto-generated method stub } @@ -464,4 +464,7 @@ public class BridgeWindowManager implements IWindowManager { public int getPreferredOptionsPanelGravity() throws RemoteException { return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; } + + public void dismissKeyguard() { + } } diff --git a/tools/orientationplot/orientationplot.py b/tools/orientationplot/orientationplot.py index 07449d4d2bc9..3a44cb2cbfd8 100755 --- a/tools/orientationplot/orientationplot.py +++ b/tools/orientationplot/orientationplot.py @@ -131,42 +131,28 @@ class Plotter: self.orientation_angle_axes, 'orientation', 'black') self._add_timeseries_legend(self.orientation_angle_axes) - self.actual_orientation = self._make_timeseries() - self.proposed_orientation = self._make_timeseries() + self.current_rotation = self._make_timeseries() + self.proposed_rotation = self._make_timeseries() + self.proposal_rotation = self._make_timeseries() self.orientation_axes = self._add_timeseries_axes( - 5, 'Actual / Proposed Orientation and Confidence', 'rotation', [-1, 4], + 5, 'Current / Proposed Orientation and Confidence', 'rotation', [-1, 4], sharex=shared_axis, yticks=range(0, 4)) - self.actual_orientation_line = self._add_timeseries_line( - self.orientation_axes, 'actual', 'black', linewidth=2) - self.proposed_orientation_line = self._add_timeseries_line( - self.orientation_axes, 'proposed', 'purple', linewidth=3) + self.current_rotation_line = self._add_timeseries_line( + self.orientation_axes, 'current', 'black', linewidth=2) + self.proposal_rotation_line = self._add_timeseries_line( + self.orientation_axes, 'proposal', 'purple', linewidth=3) + self.proposed_rotation_line = self._add_timeseries_line( + self.orientation_axes, 'proposed', 'green', linewidth=3) self._add_timeseries_legend(self.orientation_axes) - self.confidence = [[self._make_timeseries(), self._make_timeseries()] for i in range(0, 4)] - self.confidence_polys = [] - - self.combined_confidence = self._make_timeseries() - self.orientation_confidence = self._make_timeseries() - self.tilt_confidence = self._make_timeseries() - self.magnitude_confidence = self._make_timeseries() - self.confidence_axes = self._add_timeseries_axes( - 6, 'Proposed Orientation Confidence Factors', 'confidence', [-0.1, 1.1], - sharex=shared_axis, - yticks=[0.0, 0.2, 0.4, 0.6, 0.8, 1.0]) - self.combined_confidence_line = self._add_timeseries_line( - self.confidence_axes, 'combined', 'purple', linewidth=2) - self.orientation_confidence_line = self._add_timeseries_line( - self.confidence_axes, 'orientation', 'black') - self.tilt_confidence_line = self._add_timeseries_line( - self.confidence_axes, 'tilt', 'brown') - self.magnitude_confidence_line = self._add_timeseries_line( - self.confidence_axes, 'magnitude', 'orange') - self._add_timeseries_legend(self.confidence_axes) + self.proposal_confidence = [[self._make_timeseries(), self._make_timeseries()] + for i in range(0, 4)] + self.proposal_confidence_polys = [] self.sample_latency = self._make_timeseries() self.sample_latency_axes = self._add_timeseries_axes( - 7, 'Accelerometer Sampling Latency', 'ms', [-10, 500], + 6, 'Accelerometer Sampling Latency', 'ms', [-10, 500], sharex=shared_axis, yticks=range(0, 500, 100)) self.sample_latency_line = self._add_timeseries_line( @@ -186,7 +172,7 @@ class Plotter: # Add a subplot to the figure for a time series. def _add_timeseries_axes(self, index, title, ylabel, ylim, yticks, sharex=None): - num_graphs = 7 + num_graphs = 6 height = 0.9 / num_graphs top = 0.95 - height * index axes = self.fig.add_axes([0.1, top, 0.8, height], @@ -234,13 +220,10 @@ class Plotter: self.parse_magnitude = None self.parse_tilt_angle = None self.parse_orientation_angle = None - self.parse_proposed_orientation = None - self.parse_combined_confidence = None - self.parse_orientation_confidence = None - self.parse_tilt_confidence = None - self.parse_magnitude_confidence = None - self.parse_actual_orientation = None - self.parse_confidence = None + self.parse_current_rotation = None + self.parse_proposed_rotation = None + self.parse_proposal_rotation = None + self.parse_proposal_confidence = None self.parse_sample_latency = None # Update samples. @@ -284,26 +267,13 @@ class Plotter: if line.find('orientationAngle=') != -1: self.parse_orientation_angle = self._get_following_number(line, 'orientationAngle=') - if line.find('Proposal:') != -1: - self.parse_proposed_orientation = self._get_following_number(line, 'proposedOrientation=') - self.parse_combined_confidence = self._get_following_number(line, 'combinedConfidence=') - self.parse_orientation_confidence = self._get_following_number(line, 'orientationConfidence=') - self.parse_tilt_confidence = self._get_following_number(line, 'tiltConfidence=') - self.parse_magnitude_confidence = self._get_following_number(line, 'magnitudeConfidence=') - if line.find('Result:') != -1: - self.parse_actual_orientation = self._get_following_number(line, 'rotation=') - self.parse_confidence = self._get_following_array_of_numbers(line, 'confidence=') + self.parse_current_rotation = self._get_following_number(line, 'currentRotation=') + self.parse_proposed_rotation = self._get_following_number(line, 'proposedRotation=') + self.parse_proposal_rotation = self._get_following_number(line, 'proposalRotation=') + self.parse_proposal_confidence = self._get_following_number(line, 'proposalConfidence=') self.parse_sample_latency = self._get_following_number(line, 'timeDeltaMS=') - for i in range(0, 4): - if self.parse_confidence is not None: - self._append(self.confidence[i][0], timeindex, i) - self._append(self.confidence[i][1], timeindex, i + self.parse_confidence[i]) - else: - self._append(self.confidence[i][0], timeindex, None) - self._append(self.confidence[i][1], timeindex, None) - self._append(self.raw_acceleration_x, timeindex, self.parse_raw_acceleration_x) self._append(self.raw_acceleration_y, timeindex, self.parse_raw_acceleration_y) self._append(self.raw_acceleration_z, timeindex, self.parse_raw_acceleration_z) @@ -313,12 +283,22 @@ class Plotter: self._append(self.magnitude, timeindex, self.parse_magnitude) self._append(self.tilt_angle, timeindex, self.parse_tilt_angle) self._append(self.orientation_angle, timeindex, self.parse_orientation_angle) - self._append(self.actual_orientation, timeindex, self.parse_actual_orientation) - self._append(self.proposed_orientation, timeindex, self.parse_proposed_orientation) - self._append(self.combined_confidence, timeindex, self.parse_combined_confidence) - self._append(self.orientation_confidence, timeindex, self.parse_orientation_confidence) - self._append(self.tilt_confidence, timeindex, self.parse_tilt_confidence) - self._append(self.magnitude_confidence, timeindex, self.parse_magnitude_confidence) + self._append(self.current_rotation, timeindex, self.parse_current_rotation) + if self.parse_proposed_rotation >= 0: + self._append(self.proposed_rotation, timeindex, self.parse_proposed_rotation) + else: + self._append(self.proposed_rotation, timeindex, None) + if self.parse_proposal_rotation >= 0: + self._append(self.proposal_rotation, timeindex, self.parse_proposal_rotation) + else: + self._append(self.proposal_rotation, timeindex, None) + for i in range(0, 4): + self._append(self.proposal_confidence[i][0], timeindex, i) + if i == self.parse_proposal_rotation: + self._append(self.proposal_confidence[i][1], timeindex, + i + self.parse_proposal_confidence) + else: + self._append(self.proposal_confidence[i][1], timeindex, i) self._append(self.sample_latency, timeindex, self.parse_sample_latency) self._reset_parse_state() @@ -335,16 +315,13 @@ class Plotter: self._scroll(self.magnitude, bottom) self._scroll(self.tilt_angle, bottom) self._scroll(self.orientation_angle, bottom) - self._scroll(self.actual_orientation, bottom) - self._scroll(self.proposed_orientation, bottom) - self._scroll(self.combined_confidence, bottom) - self._scroll(self.orientation_confidence, bottom) - self._scroll(self.tilt_confidence, bottom) - self._scroll(self.magnitude_confidence, bottom) - self._scroll(self.sample_latency, bottom) + self._scroll(self.current_rotation, bottom) + self._scroll(self.proposed_rotation, bottom) + self._scroll(self.proposal_rotation, bottom) for i in range(0, 4): - self._scroll(self.confidence[i][0], bottom) - self._scroll(self.confidence[i][1], bottom) + self._scroll(self.proposal_confidence[i][0], bottom) + self._scroll(self.proposal_confidence[i][1], bottom) + self._scroll(self.sample_latency, bottom) # Redraw the plots. self.raw_acceleration_line_x.set_data(self.raw_acceleration_x) @@ -356,20 +333,19 @@ class Plotter: self.magnitude_line.set_data(self.magnitude) self.tilt_angle_line.set_data(self.tilt_angle) self.orientation_angle_line.set_data(self.orientation_angle) - self.actual_orientation_line.set_data(self.actual_orientation) - self.proposed_orientation_line.set_data(self.proposed_orientation) - self.combined_confidence_line.set_data(self.combined_confidence) - self.orientation_confidence_line.set_data(self.orientation_confidence) - self.tilt_confidence_line.set_data(self.tilt_confidence) - self.magnitude_confidence_line.set_data(self.magnitude_confidence) + self.current_rotation_line.set_data(self.current_rotation) + self.proposed_rotation_line.set_data(self.proposed_rotation) + self.proposal_rotation_line.set_data(self.proposal_rotation) self.sample_latency_line.set_data(self.sample_latency) - for poly in self.confidence_polys: + for poly in self.proposal_confidence_polys: poly.remove() - self.confidence_polys = [] + self.proposal_confidence_polys = [] for i in range(0, 4): - self.confidence_polys.append(self.orientation_axes.fill_between(self.confidence[i][0][0], - self.confidence[i][0][1], self.confidence[i][1][1], + self.proposal_confidence_polys.append(self.orientation_axes.fill_between( + self.proposal_confidence[i][0][0], + self.proposal_confidence[i][0][1], + self.proposal_confidence[i][1][1], facecolor='goldenrod', edgecolor='goldenrod')) self.fig.canvas.draw_idle() diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index a6ea6d422fd7..6ff1bc248cf9 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -106,12 +106,6 @@ public class WifiNative { public native static String statusCommand(); - public native static int getRssiCommand(); - - public native static int getRssiApproxCommand(); - - public native static int getLinkSpeedCommand(); - public native static String getMacAddressCommand(); public native static String scanResultsCommand(); @@ -209,6 +203,16 @@ public class WifiNative { private native static String doStringCommand(String command); + /** Example output: + * RSSI=-65 + * LINKSPEED=48 + * NOISE=9999 + * FREQUENCY=0 + */ + public static String signalPoll() { + return doStringCommand("SIGNAL_POLL"); + } + public static boolean wpsPbc() { return doBooleanCommand("WPS_PBC"); } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 052d332a7d0d..d1522fb48ce7 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -1362,7 +1362,28 @@ public class WifiStateMachine extends StateMachine { * Fetch RSSI and linkspeed on current connection */ private void fetchRssiAndLinkSpeedNative() { - int newRssi = WifiNative.getRssiCommand(); + int newRssi = -1; + int newLinkSpeed = -1; + + String signalPoll = WifiNative.signalPoll(); + + if (signalPoll != null) { + String[] lines = signalPoll.split("\n"); + for (String line : lines) { + String[] prop = line.split("="); + if (prop.length < 2) continue; + try { + if (prop[0].equals("RSSI")) { + newRssi = Integer.parseInt(prop[1]); + } else if (prop[0].equals("LINKSPEED")) { + newLinkSpeed = Integer.parseInt(prop[1]); + } + } catch (NumberFormatException e) { + //Ignore, defaults on rssi and linkspeed are assigned + } + } + } + if (newRssi != -1 && MIN_RSSI < newRssi && newRssi < MAX_RSSI) { // screen out invalid values /* some implementations avoid negative values by adding 256 * so we need to adjust for that here. @@ -1390,7 +1411,7 @@ public class WifiStateMachine extends StateMachine { } else { mWifiInfo.setRssi(MIN_RSSI); } - int newLinkSpeed = WifiNative.getLinkSpeedCommand(); + if (newLinkSpeed != -1) { mWifiInfo.setLinkSpeed(newLinkSpeed); } @@ -1539,8 +1560,9 @@ public class WifiStateMachine extends StateMachine { try { mNwService.clearInterfaceAddresses(mInterfaceName); + mNwService.disableIpv6(mInterfaceName); } catch (Exception e) { - Log.e(TAG, "Failed to clear IP addresses on disconnect" + e); + Log.e(TAG, "Failed to clear addresses or disable ipv6" + e); } /* Reset data structures */ @@ -1820,6 +1842,21 @@ public class WifiStateMachine extends StateMachine { mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE); mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger()); + /* IPv6 is disabled at boot time and is controlled by framework + * to be enabled only as long as we are connected to an access point + * + * This fixes issues, a few being: + * - IPv6 addresses and routes stick around after disconnection + * - When connected, the kernel is unaware and can fail to start IPv6 negotiation + * - The kernel sometimes starts autoconfiguration when 802.1x is not complete + */ + try { + mNwService.disableIpv6(mInterfaceName); + } catch (RemoteException re) { + Log.e(TAG, "Failed to disable IPv6: " + re); + } catch (IllegalStateException e) { + Log.e(TAG, "Failed to disable IPv6: " + e); + } } } @@ -2713,7 +2750,15 @@ public class WifiStateMachine extends StateMachine { if (DBG) Log.d(TAG, getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); - if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) { + try { + mNwService.enableIpv6(mInterfaceName); + } catch (RemoteException re) { + Log.e(TAG, "Failed to enable IPv6: " + re); + } catch (IllegalStateException e) { + Log.e(TAG, "Failed to enable IPv6: " + e); + } + + if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) { //start DHCP mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine( mContext, WifiStateMachine.this, mInterfaceName); @@ -2737,7 +2782,7 @@ public class WifiStateMachine extends StateMachine { sendMessage(CMD_STATIC_IP_FAILURE); } } - } + } @Override public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java index fe0e85093601..af8c48642799 100644 --- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java +++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java @@ -589,12 +589,11 @@ public class WifiWatchdogStateMachine extends StateMachine { updateBssids(); transitionTo(mDnsCheckingState); mNetEventCounter++; - return HANDLED; - case DISCONNECTED: - case DISCONNECTING: + break; + default: mNetEventCounter++; transitionTo(mNotConnectedState); - return HANDLED; + break; } return HANDLED; case EVENT_WIFI_RADIO_STATE_CHANGE: |