diff options
34 files changed, 316 insertions, 103 deletions
diff --git a/api/current.txt b/api/current.txt index 299a33c..eb7891a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -27271,8 +27271,8 @@ package android.speech.tts { method public boolean isSpeaking(); method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String); method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>); - method public int playSilence(long, int, java.lang.String); method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>); + method public int playSilentUtterance(long, int, java.lang.String); method public int setAudioAttributes(android.media.AudioAttributes); method public deprecated int setEngineByPackageName(java.lang.String); method public int setLanguage(java.util.Locale); diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index e659b2b..0892311 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -397,6 +397,31 @@ void BootAnimation::checkExit() { } } +// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of +// characters in str is a hex number in [0, 255], which are converted to +// floating point values in the range [0.0, 1.0] and placed in the +// corresponding elements of color. +// +// If the input string isn't valid, parseColor returns false and color is +// left unchanged. +static bool parseColor(const char str[7], float color[3]) { + float tmpColor[3]; + for (int i = 0; i < 3; i++) { + int val = 0; + for (int j = 0; j < 2; j++) { + val *= 16; + char c = str[2*i + j]; + if (c >= '0' && c <= '9') val += c - '0'; + else if (c >= 'A' && c <= 'F') val += (c - 'A') + 10; + else if (c >= 'a' && c <= 'f') val += (c - 'a') + 10; + else return false; + } + tmpColor[i] = static_cast<float>(val) / 255.0f; + } + memcpy(color, tmpColor, sizeof(tmpColor)); + return true; +} + bool BootAnimation::movie() { ZipEntryRO desc = mZip->findEntryByName("desc.txt"); @@ -427,20 +452,28 @@ bool BootAnimation::movie() const char* l = line.string(); int fps, width, height, count, pause; char path[ANIM_ENTRY_NAME_MAX]; + char color[7] = "000000"; // default to black if unspecified + char pathType; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { - //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); + // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps); animation.width = width; animation.height = height; animation.fps = fps; } - else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) { - //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path); + else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) { + // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s", pathType, count, pause, path, color); Animation::Part part; part.playUntilComplete = pathType == 'c'; part.count = count; part.pause = pause; part.path = path; + if (!parseColor(color, part.backgroundColor)) { + ALOGE("> invalid color '#%s'", color); + part.backgroundColor[0] = 0.0f; + part.backgroundColor[1] = 0.0f; + part.backgroundColor[2] = 0.0f; + } animation.parts.add(part); } @@ -526,6 +559,12 @@ bool BootAnimation::movie() if(exitPending() && !part.playUntilComplete) break; + glClearColor( + part.backgroundColor[0], + part.backgroundColor[1], + part.backgroundColor[2], + 1.0f); + for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index ba1c507..72cd62b 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -71,6 +71,7 @@ private: String8 path; SortedVector<Frame> frames; bool playUntilComplete; + float backgroundColor[3]; }; int fps; int width; diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index 3b41359..a7ea89c 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -328,6 +328,7 @@ public class RequestThreadManager { resetJpegSurfaceFormats(mCallbackOutputs); mPreviewOutputs.clear(); mCallbackOutputs.clear(); + mJpegSurfaceIds.clear(); mPreviewTexture = null; int facing = mCharacteristics.get(CameraCharacteristics.LENS_FACING); diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index ba71605..362afba 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -17,6 +17,7 @@ package android.os; import android.util.Log; +import android.util.Slog; import com.android.internal.util.FastPrintWriter; import java.io.FileDescriptor; @@ -48,7 +49,7 @@ public class Binder implements IBinder { * of classes can potentially create leaks. */ private static final boolean FIND_POTENTIAL_LEAKS = false; - private static final String TAG = "Binder"; + static final String TAG = "Binder"; /** * Control whether dump() calls are allowed. @@ -385,7 +386,14 @@ public class Binder implements IBinder { super.finalize(); } } - + + static void checkParcel(Parcel parcel, String msg) { + if (parcel.dataSize() >= 800*1024) { + // Trying to send > 800k, this is way too much + Slog.wtfStack(TAG, msg + parcel.dataSize()); + } + } + private native final void init(); private native final void destroy(); @@ -424,6 +432,7 @@ public class Binder implements IBinder { reply.writeException(re); res = true; } + checkParcel(reply, "Unreasonably large binder reply buffer: "); reply.recycle(); data.recycle(); return res; @@ -433,13 +442,18 @@ public class Binder implements IBinder { final class BinderProxy implements IBinder { public native boolean pingBinder(); public native boolean isBinderAlive(); - + public IInterface queryLocalInterface(String descriptor) { return null; } - + + public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + Binder.checkParcel(data, "Unreasonably large binder buffer: "); + return transactNative(code, data, reply, flags); + } + public native String getInterfaceDescriptor() throws RemoteException; - public native boolean transact(int code, Parcel data, Parcel reply, + public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException; public native void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 440b1ec..ec4a53e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -978,6 +978,19 @@ public final class Settings { public static final String EXTRA_INPUT_METHOD_ID = "input_method_id"; /** + * Activity Extra: The device identifier to act upon. + * <p> + * This can be passed as an extra field in an Activity Intent with a single + * InputDeviceIdentifier. This field is used by some activities to jump straight into the + * settings for the given device. + * <p> + * Example: The {@link #INPUT_METHOD_SETTINGS} intent opens the keyboard layout dialog for the + * given device. + * @hide + */ + public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier"; + + /** * @hide * Activity Extra: Enable or disable Airplane Mode. * <p> diff --git a/core/java/android/speech/tts/SynthesisRequest.java b/core/java/android/speech/tts/SynthesisRequest.java index d41aa67..6262fcb 100644 --- a/core/java/android/speech/tts/SynthesisRequest.java +++ b/core/java/android/speech/tts/SynthesisRequest.java @@ -61,7 +61,7 @@ public final class SynthesisRequest { /** * Gets the text which should be synthesized. - * @deprecated As of API level 20, replaced by {@link #getCharSequenceText}. + * @deprecated As of API level 21, replaced by {@link #getCharSequenceText}. */ @Deprecated public String getText() { diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 120c9e3..c59ca8a 100644 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -575,7 +575,7 @@ public class TextToSpeech { * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String) * @see TextToSpeech#getFeatures(java.util.Locale) * - * @deprecated Starting from API level 20, to select network synthesis, call + * @deprecated Starting from API level 21, to select network synthesis, call * ({@link TextToSpeech#getVoices()}, find a suitable network voice * ({@link Voice#isNetworkConnectionRequired()}) and pass it * to {@link TextToSpeech#setVoice(Voice)}). @@ -593,7 +593,7 @@ public class TextToSpeech { * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String) * @see TextToSpeech#getFeatures(java.util.Locale) - * @deprecated Starting from API level 20, to select embedded synthesis, call + * @deprecated Starting from API level 21, to select embedded synthesis, call * ({@link TextToSpeech#getVoices()}, find a suitable embedded voice * ({@link Voice#isNetworkConnectionRequired()}) and pass it * to {@link TextToSpeech#setVoice(Voice)}). @@ -1015,7 +1015,7 @@ public class TextToSpeech { * * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. * - * @deprecated As of API level 20, replaced by + * @deprecated As of API level 21, replaced by * {@link #addEarcon(String, File)}. */ @Deprecated @@ -1124,7 +1124,7 @@ public class TextToSpeech { * engine named "com.svox.pico" if it is being used. * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation. - * @deprecated As of API level 20, replaced by + * @deprecated As of API level 21, replaced by * {@link #speak(CharSequence, int, Bundle, String)}. */ @Deprecated @@ -1194,7 +1194,7 @@ public class TextToSpeech { * engine named "com.svox.pico" if it is being used. * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation. - * @deprecated As of API level 20, replaced by + * @deprecated As of API level 21, replaced by * {@link #playEarcon(String, int, Bundle, String)}. */ @Deprecated @@ -1218,9 +1218,9 @@ public class TextToSpeech { * @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. * @param utteranceId An unique identifier for this request. * - * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation. + * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilentUtterance operation. */ - public int playSilence(final long durationInMs, final int queueMode, + public int playSilentUtterance(final long durationInMs, final int queueMode, final String utteranceId) { return runAction(new Action<Integer>() { @Override @@ -1228,7 +1228,7 @@ public class TextToSpeech { return service.playSilence(getCallerIdentity(), durationInMs, queueMode, utteranceId); } - }, ERROR, "playSilence"); + }, ERROR, "playSilentUtterance"); } /** @@ -1252,13 +1252,13 @@ public class TextToSpeech { * engine named "com.svox.pico" if it is being used. * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation. - * @deprecated As of API level 20, replaced by - * {@link #playSilence(long, int, String)}. + * @deprecated As of API level 21, replaced by + * {@link #playSilentUtterance(long, int, String)}. */ @Deprecated public int playSilence(final long durationInMs, final int queueMode, final HashMap<String, String> params) { - return playSilence(durationInMs, queueMode, + return playSilentUtterance(durationInMs, queueMode, params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID)); } @@ -1276,7 +1276,7 @@ public class TextToSpeech { * * @param locale The locale to query features for. * @return Set instance. May return {@code null} on error. - * @deprecated As of API level 20, please use voices. In order to query features of the voice, + * @deprecated As of API level 21, please use voices. In order to query features of the voice, * call {@link #getVoices()} to retrieve the list of available voices and * {@link Voice#getFeatures()} to retrieve the set of features. */ @@ -1421,7 +1421,7 @@ public class TextToSpeech { * * @return language, country (if any) and variant (if any) used by the client stored in a * Locale instance, or {@code null} on error. - * @deprecated As of API Level 20, use <code>getDefaultVoice().getLocale()</code> ({@link + * @deprecated As of API level 21, use <code>getDefaultVoice().getLocale()</code> ({@link * #getDefaultVoice()}) */ @Deprecated @@ -1476,7 +1476,7 @@ public class TextToSpeech { String variant = loc.getVariant(); - // As of API level 20, setLanguage is implemented using setVoice. + // As of API level 21, setLanguage is implemented using setVoice. // (which, in the default implementation, will call loadLanguage on the service // interface). @@ -1535,7 +1535,7 @@ public class TextToSpeech { * @return language, country (if any) and variant (if any) used by the client stored in a * Locale instance, or {@code null} on error. * - * @deprecated As of API level 20, please use <code>getVoice().getLocale()</code> + * @deprecated As of API level 21, please use <code>getVoice().getLocale()</code> * ({@link #getVoice()}). */ @Deprecated @@ -1831,7 +1831,7 @@ public class TextToSpeech { * something like "/sdcard/myappsounds/mysound.wav". * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation. - * @deprecated As of API level 20, replaced by + * @deprecated As of API level 21, replaced by * {@link #synthesizeToFile(CharSequence, Bundle, File, String)}. */ @Deprecated diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index 079467a..9bb7f02 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -91,7 +91,7 @@ import java.util.Set; * The first three methods are siblings of the {@link #onGetLanguage}, * {@link #onIsLanguageAvailable} and {@link #onLoadLanguage} methods. The last one, * {@link #onGetDefaultVoiceNameFor(String, String, String)} is a link between locale and voice - * based methods. Since API level 20 {@link TextToSpeech#setLanguage} is implemented by + * based methods. Since API level 21 {@link TextToSpeech#setLanguage} is implemented by * calling {@link TextToSpeech#setVoice} with the voice returned by * {@link #onGetDefaultVoiceNameFor(String, String, String)}. * diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index 946a3f7..c855e57 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -81,7 +81,7 @@ public class DisplayMetrics { /** * Intermediate density for screens that sit somewhere between - * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (560 dpi). + * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (640 dpi). * This is not a density that applications should target, instead relying * on the system to scale their {@link #DENSITY_XXXHIGH} assets for them. */ diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index a283b91..baa133d 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -889,7 +889,13 @@ final class AccessibilityInteractionController { } } } else { - AccessibilityNodeInfo root = provider.createAccessibilityNodeInfo(virtualViewId); + final AccessibilityNodeInfo root; + if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { + root = provider.createAccessibilityNodeInfo(virtualViewId); + } else { + root = provider.createAccessibilityNodeInfo( + AccessibilityNodeProvider.HOST_VIEW_ID); + } if (root != null) { outInfos.add(root); if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) { diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 2b8b4dc..0439168 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -1493,11 +1493,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te super.onInitializeAccessibilityNodeInfo(info); info.setClassName(AbsListView.class.getName()); if (isEnabled()) { - if (getFirstVisiblePosition() > 0) { + if (canScrollUp()) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); info.setScrollable(true); } - if (getLastVisiblePosition() < getCount() - 1) { + if (canScrollDown()) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); info.setScrollable(true); } @@ -2203,36 +2203,44 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te void updateScrollIndicators() { if (mScrollUp != null) { - boolean canScrollUp; - // 0th element is not visible - canScrollUp = mFirstPosition > 0; - - // ... Or top of 0th element is not visible - if (!canScrollUp) { - if (getChildCount() > 0) { - View child = getChildAt(0); - canScrollUp = child.getTop() < mListPadding.top; - } - } - - mScrollUp.setVisibility(canScrollUp ? View.VISIBLE : View.INVISIBLE); + mScrollUp.setVisibility(canScrollUp() ? View.VISIBLE : View.INVISIBLE); } if (mScrollDown != null) { - boolean canScrollDown; - int count = getChildCount(); + mScrollDown.setVisibility(canScrollDown() ? View.VISIBLE : View.INVISIBLE); + } + } - // Last item is not visible - canScrollDown = (mFirstPosition + count) < mItemCount; + private boolean canScrollUp() { + boolean canScrollUp; + // 0th element is not visible + canScrollUp = mFirstPosition > 0; - // ... Or bottom of the last element is not visible - if (!canScrollDown && count > 0) { - View child = getChildAt(count - 1); - canScrollDown = child.getBottom() > mBottom - mListPadding.bottom; + // ... Or top of 0th element is not visible + if (!canScrollUp) { + if (getChildCount() > 0) { + View child = getChildAt(0); + canScrollUp = child.getTop() < mListPadding.top; } + } + + return canScrollUp; + } - mScrollDown.setVisibility(canScrollDown ? View.VISIBLE : View.INVISIBLE); + private boolean canScrollDown() { + boolean canScrollDown; + int count = getChildCount(); + + // Last item is not visible + canScrollDown = (mFirstPosition + count) < mItemCount; + + // ... Or bottom of the last element is not visible + if (!canScrollDown && count > 0) { + View child = getChildAt(count - 1); + canScrollDown = child.getBottom() > mBottom - mListPadding.bottom; } + + return canScrollDown; } @Override diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 22600de..5685ad7 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -128,7 +128,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic com.android.internal.R.string.whichSendApplicationNamed), DEFAULT(null, com.android.internal.R.string.whichApplication, - com.android.internal.R.string.whichApplicationNamed); + com.android.internal.R.string.whichApplicationNamed), + HOME(Intent.ACTION_MAIN, + com.android.internal.R.string.whichHomeApplication, + com.android.internal.R.string.whichHomeApplicationNamed); public final String action; public final int titleRes; @@ -142,7 +145,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic public static ActionTitle forAction(String action) { for (ActionTitle title : values()) { - if (action != null && action.equals(title.action)) { + if (title != HOME && action != null && action.equals(title.action)) { return title; } } @@ -165,26 +168,19 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic @Override protected void onCreate(Bundle savedInstanceState) { // Use a specialized prompt when we're handling the 'Home' app startActivity() - final int titleResource; final Intent intent = makeMyIntent(); final Set<String> categories = intent.getCategories(); if (Intent.ACTION_MAIN.equals(intent.getAction()) && categories != null && categories.size() == 1 && categories.contains(Intent.CATEGORY_HOME)) { - titleResource = com.android.internal.R.string.whichHomeApplication; - // Note: this field is not set to true in the compatibility version. mResolvingHome = true; - } else { - titleResource = 0; } setSafeForwardingMode(true); - onCreate(savedInstanceState, intent, - titleResource != 0 ? getResources().getText(titleResource) : null, titleResource, - null, null, true); + onCreate(savedInstanceState, intent, null, 0, null, null, true); } /** @@ -336,7 +332,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } protected CharSequence getTitleForAction(String action, int defaultTitleRes) { - final ActionTitle title = ActionTitle.forAction(action); + final ActionTitle title = mResolvingHome ? ActionTitle.HOME : ActionTitle.forAction(action); final boolean named = mAdapter.hasFilteredItem(); if (title == ActionTitle.DEFAULT && defaultTitleRes != 0) { return getString(defaultTitleRes); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 1a2d6ce..85b58aa 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -780,9 +780,9 @@ public class LockPatternUtils { */ public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) { try { - getLockSettings().setLockPassword(password, userHandle); DevicePolicyManager dpm = getDevicePolicyManager(); if (!TextUtils.isEmpty(password)) { + getLockSettings().setLockPassword(password, userHandle); int computedQuality = computePasswordQuality(password); if (userHandle == UserHandle.USER_OWNER) { @@ -860,6 +860,7 @@ public class LockPatternUtils { setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle); } else { // Empty password + getLockSettings().setLockPassword(null, userHandle); if (userHandle == UserHandle.USER_OWNER) { // Set the encryption password to default. updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null); diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 81e887d..2dbd382 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -1239,7 +1239,7 @@ static const JNINativeMethod gBinderProxyMethods[] = { {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, - {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, + {"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, {"destroy", "()V", (void*)android_os_BinderProxy_destroy}, diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index fd4b40f..9fc7801 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3440,7 +3440,10 @@ and a previously used application is known. --> <string name="whichSendApplicationNamed">Share with %1$s</string> <!-- Title of intent resolver dialog when selecting a HOME application to run. --> - <string name="whichHomeApplication">Select a home app</string> + <string name="whichHomeApplication">Select a Home app</string> + <!-- Title of intent resolver dialog when selecting a HOME application to run + and a previously used application is known. --> + <string name="whichHomeApplicationNamed">Use %1$s as Home</string> <!-- Option to always use the selected application resolution in the future. See the "Complete action using" dialog title--> <string name="alwaysUse">Use by default for this action.</string> <!-- Title of the list of alternate options to complete an action shown when the diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 2620c27..72f756a 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2067,4 +2067,5 @@ <java-symbol type="bool" name="config_restart_radio_on_pdp_fail_regular_deactivation" /> <java-symbol type="array" name="networks_not_clear_data" /> <java-symbol type="bool" name="config_switch_phone_on_voice_reg_state_change" /> + <java-symbol type="string" name="whichHomeApplicationNamed" /> </resources> diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index f0a2072..e9e475c 100644 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -289,7 +289,7 @@ public class GpsNetInitiatedHandler { + " mPopupImmediately: " + mPopupImmediately + " mInEmergency: " + getInEmergency()); - if (getLocationEnabled() && !getInEmergency()) { + if (!getLocationEnabled() && !getInEmergency()) { // Location is currently disabled, ignore all NI requests. try { mNetInitiatedListener.sendNiResponse(notif.notificationId, diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java index 1de8a8b..3e5919f 100644 --- a/media/java/android/media/browse/MediaBrowser.java +++ b/media/java/android/media/browse/MediaBrowser.java @@ -141,26 +141,31 @@ public final class MediaBrowser { final ServiceConnection thisConnection = mServiceConnection = new MediaServiceConnection(); + boolean bound = false; try { - mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); + if (mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)) { + bound = true; + } } catch (Exception ex) { Log.e(TAG, "Failed binding to service " + mServiceComponent); + } + if (!bound) { // Tell them that it didn't work. We are already on the main thread, // but we don't want to do callbacks inside of connect(). So post it, // and then check that we are on the same ServiceConnection. We know // we won't also get an onServiceConnected or onServiceDisconnected, // so we won't be doing double callbacks. mHandler.post(new Runnable() { - @Override - public void run() { - // Ensure that nobody else came in or tried to connect again. - if (thisConnection == mServiceConnection) { - forceCloseConnection(); - mCallback.onConnectionFailed(); - } + @Override + public void run() { + // Ensure that nobody else came in or tried to connect again. + if (thisConnection == mServiceConnection) { + forceCloseConnection(); + mCallback.onConnectionFailed(); } - }); + } + }); } if (DBG) { diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 8267846..13170ad 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -244,6 +244,6 @@ <integer name="zen_toast_animation_duration">500</integer> <!-- Zen toast visibility duration --> - <integer name="zen_toast_visible_duration">2000</integer> + <integer name="zen_toast_visible_duration">500</integer> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 8e603ba..0d393bf 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -412,7 +412,7 @@ public class SwipeHelper implements Gefingerpoken { if (mCurrView != null) { float delta = getPos(ev) - mInitialTouchPos; float absDelta = Math.abs(delta); - if (absDelta >= mFalsingThreshold) { + if (absDelta >= getFalsingThreshold()) { mTouchAboveFalsingThreshold = true; } // don't let items that can't be dismissed be dragged more than @@ -466,6 +466,11 @@ public class SwipeHelper implements Gefingerpoken { return true; } + private int getFalsingThreshold() { + float factor = mCallback.getFalsingThresholdFactor(); + return (int) (mFalsingThreshold * factor); + } + public interface Callback { View getChildAtPosition(MotionEvent ev); @@ -489,6 +494,11 @@ public class SwipeHelper implements Gefingerpoken { * @return if true, prevents the default alpha fading. */ boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress); + + /** + * @return The factor the falsing threshold should be multiplied with + */ + float getFalsingThresholdFactor(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java index bdb0ad3..330333a 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java @@ -196,6 +196,11 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView return false; } + @Override + public float getFalsingThresholdFactor() { + return 1.0f; + } + public void dismissChild(View v) { mSwipeHelper.dismissChild(v, 0); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index 47c096f..1e247be 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java @@ -204,6 +204,11 @@ public class RecentsVerticalScrollView extends ScrollView return false; } + @Override + public float getFalsingThresholdFactor() { + return 1.0f; + } + public void dismissChild(View v) { mSwipeHelper.dismissChild(v, 0); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java index a9c701a..6653254 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -303,8 +303,12 @@ public class KeyguardAffordanceHelper { } private boolean isBelowFalsingThreshold() { - return Math.abs(mTranslation) < Math.abs(mTranslationOnDown) - + mMinTranslationAmount; + return Math.abs(mTranslation) < Math.abs(mTranslationOnDown) + getMinTranslationAmount(); + } + + private int getMinTranslationAmount() { + float factor = mCallback.getAffordanceFalsingFactor(); + return (int) (mMinTranslationAmount * factor); } private void fling(float vel, final boolean snapBack) { @@ -339,14 +343,14 @@ public class KeyguardAffordanceHelper { translation = rightSwipePossible() ? translation : Math.max(0, translation); translation = leftSwipePossible() ? translation : Math.min(0, translation); float absTranslation = Math.abs(translation); - if (absTranslation > Math.abs(mTranslationOnDown) + mMinTranslationAmount || + if (absTranslation > Math.abs(mTranslationOnDown) + getMinTranslationAmount() || mMotionPerformedByUser) { mMotionPerformedByUser = true; } if (translation != mTranslation || isReset) { KeyguardAffordanceView targetView = translation > 0 ? mLeftIcon : mRightIcon; KeyguardAffordanceView otherView = translation > 0 ? mRightIcon : mLeftIcon; - float alpha = absTranslation / mMinTranslationAmount; + float alpha = absTranslation / getMinTranslationAmount(); // We interpolate the alpha of the other icons to 0 float fadeOutAlpha = SWIPE_RESTING_ALPHA_AMOUNT * (1.0f - alpha); @@ -482,5 +486,10 @@ public class KeyguardAffordanceHelper { View getLeftPreview(); View getRightPreview(); + + /** + * @return The factor the minimum swipe amount should be multiplied with. + */ + float getAffordanceFalsingFactor(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 80e9663..2efa84a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -706,7 +706,7 @@ public class NotificationPanelView extends PanelView implements case MotionEvent.ACTION_MOVE: final float h = y - mInitialTouchY; setQsExpansion(h + mInitialHeightOnTouch); - if (h >= mQsFalsingThreshold) { + if (h >= getFalsingThreshold()) { mQsTouchAboveFalsingThreshold = true; } trackMovement(event); @@ -732,6 +732,11 @@ public class NotificationPanelView extends PanelView implements } } + private int getFalsingThreshold() { + float factor = mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f; + return (int) (mQsFalsingThreshold * factor); + } + @Override public void onOverscrolled(float lastTouchX, float lastTouchY, int amount) { if (mIntercepting && shouldQuickSettingsIntercept(lastTouchX, lastTouchY, @@ -1633,6 +1638,11 @@ public class NotificationPanelView extends PanelView implements } @Override + public float getAffordanceFalsingFactor() { + return mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f; + } + + @Override protected float getPeekHeight() { if (mNotificationStackScroller.getNotGoneChildCount() > 0) { return mNotificationStackScroller.getPeekHeight(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java index 7f155a1..84216a4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java @@ -316,6 +316,11 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper. } @Override + public float getFalsingThresholdFactor() { + return 1.0f; + } + + @Override public void onChildDismissed(View v) { Log.v(TAG, "User swiped heads up to dismiss"); mBar.onHeadsUpDismissed(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 67ba8d2..4a20406 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -547,6 +547,11 @@ public class NotificationStackScrollLayout extends ViewGroup return false; } + @Override + public float getFalsingThresholdFactor() { + return mPhoneStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f; + } + public void onBeginDrag(View v) { setSwipingInProgress(true); mAmbientState.onBeginDrag(v); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index f72b12f..be3fc47 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -759,7 +759,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } int getActiveWindowId() { - return mSecurityPolicy.mActiveWindowId; + return mSecurityPolicy.getActiveWindowId(); } void onTouchInteractionStart() { @@ -2600,6 +2600,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { userState.mInstalledServices.remove(mAccessibilityServiceInfo); userState.mEnabledServices.remove(mComponentName); userState.destroyUiAutomationService(); + if (readConfigurationForUserStateLocked(userState)) { + onUserStateChangedLocked(userState); + } } } } @@ -2820,7 +2823,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) { - return mSecurityPolicy.mActiveWindowId; + return mSecurityPolicy.getActiveWindowId(); } return accessibilityWindowId; } @@ -3281,7 +3284,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public void clearWindowsLocked() { List<AccessibilityWindowInfo> windows = Collections.emptyList(); + final int activeWindowId = mActiveWindowId; updateWindowsLocked(windows); + mActiveWindowId = activeWindowId; mWindows = null; } @@ -3494,6 +3499,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + public int getActiveWindowId() { + if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) { + mActiveWindowId = getFocusedWindowId(); + } + return mActiveWindowId; + } + private void setActiveWindowLocked(int windowId) { if (mActiveWindowId != windowId) { mActiveWindowId = windowId; diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 8e8e4a6..01e80b7 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2134,7 +2134,8 @@ public final class ActiveServices { if (!hasCreate) { continue; } - if (proc != null && !proc.persistent && proc.thread != null + // XXX turned off for now until we have more time to get a better policy. + if (false && proc != null && !proc.persistent && proc.thread != null && proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID && proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { proc.kill("bound to service " + sr.name.flattenToShortString() diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d2e3d25..4d2fd4c 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4690,8 +4690,8 @@ public final class ActivityManagerService extends ActivityManagerNative private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { int pid = app.pid; - cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); - if (!restarting) { + boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); + if (!kept && !restarting) { removeLruProcessLocked(app); if (pid > 0) { ProcessList.remove(pid); @@ -4816,6 +4816,14 @@ public final class ActivityManagerService extends ActivityManagerNative } final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread) { + // First check if this ProcessRecord is actually active for the pid. + synchronized (mPidsSelfLocked) { + ProcessRecord curProc = mPidsSelfLocked.get(pid); + if (curProc != app) { + Slog.w(TAG, "Spurious death for " + app + ", curProc for " + pid + ": " + curProc); + return; + } + } BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); synchronized (stats) { @@ -4833,7 +4841,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean doOomAdj = doLowMem; if (!app.killedByAm) { Slog.i(TAG, "Process " + app.processName + " (pid " + pid - + ") has died."); + + ") has died"); mAllowLowerMemLevel = true; } else { // Note that we always want to do oom adj to update our state with the @@ -14310,8 +14318,11 @@ public final class ActivityManagerService extends ActivityManagerNative * Main code for cleaning up a process when it has gone away. This is * called both as a result of the process dying, or directly when stopping * a process when running in single process mode. + * + * @return Returns true if the given process has been restarted, so the + * app that was passed in must remain on the process lists. */ - private final void cleanUpApplicationRecordLocked(ProcessRecord app, + private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, boolean allowRestart, int index) { if (index >= 0) { removeLruProcessLocked(app); @@ -14434,7 +14445,7 @@ public final class ActivityManagerService extends ActivityManagerNative // If the caller is restarting this app, then leave it in its // current lists and let the caller take care of it. if (restarting) { - return; + return false; } if (!app.persistent || app.isolated) { @@ -14470,8 +14481,12 @@ public final class ActivityManagerService extends ActivityManagerNative if (restart && !app.isolated) { // We have components that still need to be running in the // process, so re-launch it. + if (index < 0) { + ProcessList.remove(app.pid); + } mProcessNames.put(app.processName, app.uid, app); startProcessLocked(app, "restart", app.processName); + return true; } else if (app.pid > 0 && app.pid != MY_PID) { // Goodbye! boolean removed; @@ -14485,6 +14500,7 @@ public final class ActivityManagerService extends ActivityManagerNative } app.setPid(0); } + return false; } boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) { diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 7f89947..15dcd44 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -695,6 +695,8 @@ public class InputManagerService extends IInputManager.Stub final int numFullKeyboards = mTempFullKeyboards.size(); boolean missingLayoutForExternalKeyboard = false; boolean missingLayoutForExternalKeyboardAdded = false; + boolean multipleMissingLayoutsForExternalKeyboardsAdded = false; + InputDevice keyboardMissingLayout = null; synchronized (mDataStore) { for (int i = 0; i < numFullKeyboards; i++) { final InputDevice inputDevice = mTempFullKeyboards.get(i); @@ -704,13 +706,25 @@ public class InputManagerService extends IInputManager.Stub missingLayoutForExternalKeyboard = true; if (i < numFullKeyboardsAdded) { missingLayoutForExternalKeyboardAdded = true; + if (keyboardMissingLayout == null) { + keyboardMissingLayout = inputDevice; + } else { + multipleMissingLayoutsForExternalKeyboardsAdded = true; + } } } } } if (missingLayoutForExternalKeyboard) { if (missingLayoutForExternalKeyboardAdded) { - showMissingKeyboardLayoutNotification(); + if (multipleMissingLayoutsForExternalKeyboardsAdded) { + // We have more than one keyboard missing a layout, so drop the + // user at the generic input methods page so they can pick which + // one to set. + showMissingKeyboardLayoutNotification(null); + } else { + showMissingKeyboardLayoutNotification(keyboardMissingLayout); + } } } else if (mKeyboardLayoutNotificationShown) { hideMissingKeyboardLayoutNotification(); @@ -761,16 +775,17 @@ public class InputManagerService extends IInputManager.Stub } // Must be called on handler. - private void showMissingKeyboardLayoutNotification() { + private void showMissingKeyboardLayoutNotification(InputDevice device) { if (!mKeyboardLayoutNotificationShown) { - if (mKeyboardLayoutIntent == null) { - final Intent intent = new Intent("android.settings.INPUT_METHOD_SETTINGS"); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - | Intent.FLAG_ACTIVITY_CLEAR_TOP); - mKeyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0, - intent, 0, null, UserHandle.CURRENT); + final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS); + if (device != null) { + intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, device.getIdentifier()); } + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0, + intent, 0, null, UserHandle.CURRENT); Resources r = mContext.getResources(); Notification notification = new Notification.Builder(mContext) @@ -778,7 +793,7 @@ public class InputManagerService extends IInputManager.Stub R.string.select_keyboard_layout_notification_title)) .setContentText(r.getString( R.string.select_keyboard_layout_notification_message)) - .setContentIntent(mKeyboardLayoutIntent) + .setContentIntent(keyboardLayoutIntent) .setSmallIcon(R.drawable.ic_settings_language) .setPriority(Notification.PRIORITY_LOW) .setColor(mContext.getResources().getColor( diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java index 796725b..b18cb96 100644 --- a/telecomm/java/android/telecom/RemoteConference.java +++ b/telecomm/java/android/telecom/RemoteConference.java @@ -166,6 +166,20 @@ public final class RemoteConference { } } + public void merge() { + try { + mConnectionService.mergeConference(mId); + } catch (RemoteException e) { + } + } + + public void swap() { + try { + mConnectionService.swapConference(mId); + } catch (RemoteException e) { + } + } + public void hold() { try { mConnectionService.hold(mId); diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index b8c3454..77d3beb 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -3310,6 +3310,19 @@ ResourceTable::Entry::Entry(const Entry& entry) , mParentId(entry.mParentId) , mPos(entry.mPos) {} +ResourceTable::Entry& ResourceTable::Entry::operator=(const Entry& entry) { + mName = entry.mName; + mParent = entry.mParent; + mType = entry.mType; + mItem = entry.mItem; + mItemFormat = entry.mItemFormat; + mBag = entry.mBag; + mNameIndex = entry.mNameIndex; + mParentId = entry.mParentId; + mPos = entry.mPos; + return *this; +} + status_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos) { if (mType == TYPE_BAG) { @@ -4352,7 +4365,11 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) { String8(entriesToAdd[i].value->getName()).string(), entriesToAdd[i].key.toString().string()); - c->addEntry(entriesToAdd[i].key, entriesToAdd[i].value); + sp<Entry> newEntry = t->getEntry(c->getName(), + entriesToAdd[i].value->getPos(), + &entriesToAdd[i].key); + + *newEntry = *entriesToAdd[i].value; } } } diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index c548a85..eac5dd3 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -316,6 +316,7 @@ public: { } Entry(const Entry& entry); + Entry& operator=(const Entry& entry); virtual ~Entry() { } |
