diff options
32 files changed, 287 insertions, 160 deletions
diff --git a/api/current.txt b/api/current.txt index d377109..4332833 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11431,7 +11431,7 @@ package android.net { method public android.net.NetworkInfo getActiveNetworkInfo(); method public android.net.NetworkQuotaInfo getActiveNetworkQuotaInfo(); method public android.net.NetworkInfo[] getAllNetworkInfo(); - method public boolean getBackgroundDataSetting(); + method public deprecated boolean getBackgroundDataSetting(); method public android.net.NetworkInfo getNetworkInfo(int); method public int getNetworkPreference(); method public static boolean isNetworkTypeValid(int); @@ -17087,7 +17087,7 @@ package android.provider { field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins"; field public static final java.lang.String ALLOW_MOCK_LOCATION = "mock_location"; field public static final java.lang.String ANDROID_ID = "android_id"; - field public static final java.lang.String BACKGROUND_DATA = "background_data"; + field public static final deprecated java.lang.String BACKGROUND_DATA = "background_data"; field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on"; field public static final android.net.Uri CONTENT_URI; field public static final java.lang.String DATA_ROAMING = "data_roaming"; diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 53fd50d..9c96883 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.os.Binder; +import android.os.Build.VERSION_CODES; import android.os.RemoteException; import java.net.InetAddress; @@ -503,16 +504,19 @@ public class ConnectivityManager { * <p> * All applications that have background services that use the network * should listen to {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}. + * <p> + * As of {@link VERSION_CODES#ICE_CREAM_SANDWICH}, availability of + * background data depends on several combined factors, and this method will + * always return {@code true}. Instead, when background data is unavailable, + * {@link #getActiveNetworkInfo()} will now appear disconnected. * * @return Whether background data usage is allowed. */ + @Deprecated public boolean getBackgroundDataSetting() { - try { - return mService.getBackgroundDataSetting(); - } catch (RemoteException e) { - // Err on the side of safety - return false; - } + // assume that background data is allowed; final authority is + // NetworkInfo which may be blocked. + return true; } /** @@ -525,11 +529,9 @@ public class ConnectivityManager { * @see #getBackgroundDataSetting() * @hide */ + @Deprecated public void setBackgroundDataSetting(boolean allowBackgroundData) { - try { - mService.setBackgroundDataSetting(allowBackgroundData); - } catch (RemoteException e) { - } + // ignored } /** diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index f391200..1b95b60 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -63,10 +63,6 @@ interface IConnectivityManager boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress); - boolean getBackgroundDataSetting(); - - void setBackgroundDataSetting(boolean allowBackgroundData); - boolean getMobileDataEnabled(); void setMobileDataEnabled(boolean enabled); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index de06f20..554afd2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3081,6 +3081,7 @@ public final class Settings { * Whether background data usage is allowed by the user. See * ConnectivityManager for more info. */ + @Deprecated public static final String BACKGROUND_DATA = "background_data"; /** diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 642aa22..77f6776 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -1807,7 +1807,9 @@ public class WebSettings { * @hide */ public void setProperty(String key, String value) { - mWebView.nativeSetProperty(key, value); + if (mWebView.nativeSetProperty(key, value)) { + mWebView.contentInvalidateAll(); + } } /** diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 17dfbe0..5d776fd 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -9278,6 +9278,6 @@ public class WebView extends AbsoluteLayout */ private native boolean nativeScrollLayer(int layer, int newX, int newY); private native int nativeGetBackgroundColor(); - native void nativeSetProperty(String key, String value); + native boolean nativeSetProperty(String key, String value); native String nativeGetProperty(String key); } diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java index 45d73af..6a84626 100644 --- a/core/java/android/widget/ActivityChooserView.java +++ b/core/java/android/widget/ActivityChooserView.java @@ -156,7 +156,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod * @param attrs A collection of attributes. */ public ActivityChooserView(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.actionButtonStyle); + this(context, attrs, 0); } /** diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index 5c42579..dd75925 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -391,7 +391,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter { final boolean inGroup = seenGroups.get(groupId); boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0 && (!mStrictWidthLimit || cellsRemaining > 0); - maxActions--; if (isAction) { View v = getItemView(item, mScrapActionButtonView, parent); @@ -430,11 +429,15 @@ public class ActionMenuPresenter extends BaseMenuPresenter { for (int j = 0; j < i; j++) { MenuItemImpl areYouMyGroupie = visibleItems.get(j); if (areYouMyGroupie.getGroupId() == groupId) { + // Give back the action slot + if (areYouMyGroupie.isActionButton()) maxActions++; areYouMyGroupie.setIsActionButton(false); } } } + if (isAction) maxActions--; + item.setIsActionButton(isAction); } } diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index 5e70e4c..5622b44 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -567,7 +567,7 @@ public class MenuBuilder implements Menu { } } - if (changedAtLeastOneItem) onItemsChanged(false); + if (changedAtLeastOneItem) onItemsChanged(true); } public void setGroupEnabled(int group, boolean enabled) { @@ -929,6 +929,7 @@ public class MenuBuilder implements Menu { * * @param structureChanged true if the menu structure changed, * false if only item properties changed. + * (Visibility is a structural property since it affects layout.) */ void onItemsChanged(boolean structureChanged) { if (!mPreventDispatchingItemsChanged) { @@ -971,7 +972,7 @@ public class MenuBuilder implements Menu { void onItemVisibleChanged(MenuItemImpl item) { // Notify of items being changed mIsVisibleItemsStale = true; - onItemsChanged(false); + onItemsChanged(true); } /** @@ -981,7 +982,7 @@ public class MenuBuilder implements Menu { void onItemActionRequestChanged(MenuItemImpl item) { // Notify of items being changed mIsActionItemsStale = true; - onItemsChanged(false); + onItemsChanged(true); } ArrayList<MenuItemImpl> getVisibleItems() { diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 8b53bb8..04147ab 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -585,7 +585,7 @@ public final class MenuItemImpl implements MenuItem { public MenuItem setActionProvider(ActionProvider actionProvider) { mActionView = null; mActionProvider = actionProvider; - mMenu.onItemsChanged(false); + mMenu.onItemsChanged(true); // Measurement can be changed return this; } diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index b432d65..b8f2d6f 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -385,7 +385,8 @@ class JavaDeathRecipient : public IBinder::DeathRecipient { public: JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list) - : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), mList(list) + : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), + mObjectWeak(NULL), mList(list) { // These objects manage their own lifetimes so are responsible for final bookkeeping. // The list holds a strong reference to this object. @@ -398,16 +399,23 @@ public: void binderDied(const wp<IBinder>& who) { - JNIEnv* env = javavm_to_jnienv(mVM); - LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this); + if (mObject != NULL) { + JNIEnv* env = javavm_to_jnienv(mVM); + + env->CallStaticVoidMethod(gBinderProxyOffsets.mClass, + gBinderProxyOffsets.mSendDeathNotice, mObject); + jthrowable excep = env->ExceptionOccurred(); + if (excep) { + report_exception(env, excep, + "*** Uncaught exception returned from death notification!"); + } - env->CallStaticVoidMethod(gBinderProxyOffsets.mClass, - gBinderProxyOffsets.mSendDeathNotice, mObject); - jthrowable excep = env->ExceptionOccurred(); - if (excep) { - report_exception(env, excep, - "*** Uncaught exception returned from death notification!"); + // Demote from strong ref to weak after binderDied() has been delivered, + // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed. + mObjectWeak = env->NewWeakGlobalRef(mObject); + env->DeleteGlobalRef(mObject); + mObject = NULL; } } @@ -423,8 +431,17 @@ public: } bool matches(jobject obj) { + bool result; JNIEnv* env = javavm_to_jnienv(mVM); - return env->IsSameObject(obj, mObject); + + if (mObject != NULL) { + result = env->IsSameObject(obj, mObject); + } else { + jobject me = env->NewLocalRef(mObjectWeak); + result = env->IsSameObject(obj, me); + env->DeleteLocalRef(me); + } + return result; } protected: @@ -433,12 +450,17 @@ protected: //LOGI("Removing death ref: recipient=%p\n", mObject); android_atomic_dec(&gNumDeathRefs); JNIEnv* env = javavm_to_jnienv(mVM); - env->DeleteGlobalRef(mObject); + if (mObject != NULL) { + env->DeleteGlobalRef(mObject); + } else { + env->DeleteWeakGlobalRef(mObjectWeak); + } } private: - JavaVM* const mVM; - jobject const mObject; + JavaVM* const mVM; + jobject mObject; + jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied() wp<DeathRecipientList> mList; }; @@ -512,7 +534,7 @@ jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) if (val->checkSubclass(&gBinderOffsets)) { // One of our own! jobject object = static_cast<JavaBBinder*>(val.get())->object(); - //printf("objectForBinder %p: it's our own %p!\n", val.get(), object); + LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object); return object; } @@ -528,7 +550,7 @@ jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) LOGV("objectForBinder %p: found existing %p!\n", val.get(), res); return res; } - LOGV("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); + LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); android_atomic_dec(&gNumProxyRefs); val->detachObject(&gBinderProxyOffsets); env->DeleteGlobalRef(object); diff --git a/core/res/res/layout/activity_chooser_view.xml b/core/res/res/layout/activity_chooser_view.xml index 5d82a97..82e1f83 100644 --- a/core/res/res/layout/activity_chooser_view.xml +++ b/core/res/res/layout/activity_chooser_view.xml @@ -22,7 +22,8 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" - style="?android:attr/actionButtonStyle"> + style="?android:attr/actionButtonStyle" + android:padding="0dip"> <FrameLayout android:id="@+id/default_activity_button" @@ -31,7 +32,7 @@ android:layout_gravity="center" android:focusable="true" android:addStatesFromChildren="true" - android:background="?android:attr/selectableItemBackground"> + android:background="?android:attr/actionBarItemBackground"> <ImageView android:id="@+id/image" android:layout_width="32dip" @@ -53,7 +54,7 @@ android:layout_gravity="center" android:focusable="true" android:addStatesFromChildren="true" - android:background="?android:attr/selectableItemBackground"> + android:background="?android:attr/actionBarItemBackground"> <ImageView android:id="@+id/image" android:layout_width="32dip" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 40355e3..aa3397f 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5264,9 +5264,9 @@ <!-- Specifies a background drawable for the action bar. --> <attr name="background" /> <!-- Specifies a background drawable for a second stacked row of the action bar. --> - <attr name="backgroundStacked" format="reference" /> + <attr name="backgroundStacked" format="reference|color" /> <!-- Specifies a background drawable for the bottom component of a split action bar. --> - <attr name="backgroundSplit" format="reference" /> + <attr name="backgroundSplit" format="reference|color" /> <!-- Specifies a layout for custom navigation. Overrides navigationMode. --> <attr name="customNavigationLayout" format="reference" /> <!-- Specifies a fixed height. --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 128889c..6aff54e 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3099,7 +3099,7 @@ <!-- Notification title when mobile data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] --> <string name="data_usage_mobile_limit_title">Mobile data disabled</string> <!-- Notification body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] --> - <string name="data_usage_limit_body">tap to enable</string> + <string name="data_usage_limit_body">Touch to enable</string> <!-- Notification title when 2G-3G data usage has exceeded limit threshold. [CHAR LIMIT=32] --> <string name="data_usage_3g_limit_snoozed_title">2G-3G data limit exceeded</string> @@ -3110,6 +3110,11 @@ <!-- Notification body when data usage has exceeded limit threshold. [CHAR LIMIT=32] --> <string name="data_usage_limit_snoozed_body"><xliff:g id="size" example="3.8GB">%s</xliff:g> over specified limit</string> + <!-- Notification title when background data usage is limited. [CHAR LIMIT=32] --> + <string name="data_usage_restricted_title">Background data restricted</string> + <!-- Notification body when background data usage is limited. [CHAR LIMIT=32] --> + <string name="data_usage_restricted_body">Touch to remove restriction</string> + <!-- SSL Certificate dialogs --> <!-- Title for an SSL Certificate dialog --> <string name="ssl_certificate">Security certificate</string> diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index dba98a3..6b31ca4 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -132,9 +132,10 @@ public: virtual status_t turnElectronBeamOff(int32_t mode) = 0; virtual status_t turnElectronBeamOn(int32_t mode) = 0; - /* verify that an ISurface was created by SurfaceFlinger. + /* verify that an ISurfaceTexture was created by SurfaceFlinger. */ - virtual bool authenticateSurface(const sp<ISurface>& surface) const = 0; + virtual bool authenticateSurfaceTexture( + const sp<ISurfaceTexture>& surface) const = 0; }; // ---------------------------------------------------------------------------- diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index c1156d5..030a83e 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -31,6 +31,8 @@ #include <ui/DisplayInfo.h> +#include <gui/ISurfaceTexture.h> + #include <utils/Log.h> // --------------------------------------------------------------------------- @@ -166,35 +168,36 @@ public: return reply.readInt32(); } - virtual bool authenticateSurface(const sp<ISurface>& surface) const + virtual bool authenticateSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) const { Parcel data, reply; int err = NO_ERROR; err = data.writeInterfaceToken( ISurfaceComposer::getInterfaceDescriptor()); if (err != NO_ERROR) { - LOGE("ISurfaceComposer::authenticateSurface: error writing " + LOGE("ISurfaceComposer::authenticateSurfaceTexture: error writing " "interface descriptor: %s (%d)", strerror(-err), -err); return false; } - err = data.writeStrongBinder(surface->asBinder()); + err = data.writeStrongBinder(surfaceTexture->asBinder()); if (err != NO_ERROR) { - LOGE("ISurfaceComposer::authenticateSurface: error writing strong " - "binder to parcel: %s (%d)", strerror(-err), -err); + LOGE("ISurfaceComposer::authenticateSurfaceTexture: error writing " + "strong binder to parcel: %s (%d)", strerror(-err), -err); return false; } err = remote()->transact(BnSurfaceComposer::AUTHENTICATE_SURFACE, data, &reply); if (err != NO_ERROR) { - LOGE("ISurfaceComposer::authenticateSurface: error performing " - "transaction: %s (%d)", strerror(-err), -err); + LOGE("ISurfaceComposer::authenticateSurfaceTexture: error " + "performing transaction: %s (%d)", strerror(-err), -err); return false; } int32_t result = 0; err = reply.readInt32(&result); if (err != NO_ERROR) { - LOGE("ISurfaceComposer::authenticateSurface: error retrieving " - "result: %s (%d)", strerror(-err), -err); + LOGE("ISurfaceComposer::authenticateSurfaceTexture: error " + "retrieving result: %s (%d)", strerror(-err), -err); return false; } return result != 0; @@ -291,8 +294,9 @@ status_t BnSurfaceComposer::onTransact( } break; case AUTHENTICATE_SURFACE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder()); - int32_t result = authenticateSurface(surface) ? 1 : 0; + sp<ISurfaceTexture> surfaceTexture = + interface_cast<ISurfaceTexture>(data.readStrongBinder()); + int32_t result = authenticateSurfaceTexture(surfaceTexture) ? 1 : 0; reply->writeInt32(result); } break; default: diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 2c70251..54d04aa 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -342,9 +342,6 @@ sp<IBinder> Surface::asBinder() const { int Surface::query(int what, int* value) const { switch (what) { - case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: - *value = 1; - return NO_ERROR; case NATIVE_WINDOW_CONCRETE_TYPE: *value = NATIVE_WINDOW_SURFACE; return NO_ERROR; diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index e91be84..5a35b4d 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -18,6 +18,8 @@ //#define LOG_NDEBUG 0 #include <gui/SurfaceTextureClient.h> +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/SurfaceComposerClient.h> #include <utils/Log.h> @@ -234,7 +236,15 @@ int SurfaceTextureClient::query(int what, int* value) const { } break; case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: - *value = 0; + { + sp<ISurfaceComposer> composer( + ComposerService::getComposerService()); + if (composer->authenticateSurfaceTexture(mSurfaceTexture)) { + *value = 1; + } else { + *value = 0; + } + } return NO_ERROR; case NATIVE_WINDOW_CONCRETE_TYPE: *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT; diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 8b23da7..f2673b3 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -549,7 +549,7 @@ void AwesomePlayer::reset_l() { mVideoTimeUs = 0; mSeeking = NO_SEEK; - mSeekNotificationSent = false; + mSeekNotificationSent = true; mSeekTimeUs = 0; mUri.setTo(""); @@ -1210,7 +1210,6 @@ void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) { if (mLastVideoTimeUs >= 0) { mSeeking = SEEK; - mSeekNotificationSent = true; mSeekTimeUs = mLastVideoTimeUs; modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); } @@ -1311,8 +1310,10 @@ void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) { } void AwesomePlayer::onRTSPSeekDone() { - notifyListener_l(MEDIA_SEEK_COMPLETE); - mSeekNotificationSent = true; + if (!mSeekNotificationSent) { + notifyListener_l(MEDIA_SEEK_COMPLETE); + mSeekNotificationSent = true; + } } status_t AwesomePlayer::seekTo_l(int64_t timeUs) { diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 22ce484..1341dd4 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -163,8 +163,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean mTestMode; private static ConnectivityService sServiceInstance; - private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true); - private INetworkManagementService mNetd; private INetworkPolicyManager mPolicyManager; @@ -213,13 +211,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { MAX_NETWORK_STATE_TRACKER_EVENT + 5; /** - * used internally to set the background data preference - * arg1 = TRUE for enabled, FALSE for disabled - */ - private static final int EVENT_SET_BACKGROUND_DATA = - MAX_NETWORK_STATE_TRACKER_EVENT + 6; - - /** * used internally to set enable/disable cellular data * arg1 = ENBALED or DISABLED */ @@ -317,9 +308,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { handlerThread.start(); mHandler = new MyHandler(handlerThread.getLooper()); - mBackgroundDataEnabled.set(Settings.Secure.getInt(context.getContentResolver(), - Settings.Secure.BACKGROUND_DATA, 1) == 1); - // setup our unique device name if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) { String id = Settings.Secure.getString(context.getContentResolver(), @@ -1209,35 +1197,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { } /** - * @see ConnectivityManager#getBackgroundDataSetting() - */ - public boolean getBackgroundDataSetting() { - return mBackgroundDataEnabled.get(); - } - - /** - * @see ConnectivityManager#setBackgroundDataSetting(boolean) - */ - public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING, - "ConnectivityService"); - - mBackgroundDataEnabled.set(allowBackgroundDataUsage); - - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA, - (allowBackgroundDataUsage ? ENABLED : DISABLED), 0)); - } - - private void handleSetBackgroundData(boolean enabled) { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0); - Intent broadcast = new Intent( - ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); - mContext.sendBroadcast(broadcast); - } - - /** * @see ConnectivityManager#getMobileDataEnabled() */ public boolean getMobileDataEnabled() { @@ -2273,12 +2232,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { handleSetNetworkPreference(preference); break; } - case EVENT_SET_BACKGROUND_DATA: - { - boolean enabled = (msg.arg1 == ENABLED); - handleSetBackgroundData(enabled); - break; - } case EVENT_SET_MOBILE_DATA: { boolean enabled = (msg.arg1 == ENABLED); diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 9c3d166..14d9665 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -89,6 +89,7 @@ import android.os.IPowerManager; import android.os.Message; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.format.Formatter; import android.text.format.Time; @@ -168,6 +169,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final String ATTR_UID = "uid"; private static final String ATTR_POLICY = "policy"; + private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground"; + + // @VisibleForTesting + public static final String ACTION_ALLOW_BACKGROUND = + "com.android.server.action.ACTION_ALLOW_BACKGROUND"; + private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS; private static final int MSG_RULES_CHANGED = 0x1; @@ -185,8 +192,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final Object mRulesLock = new Object(); - private boolean mScreenOn; - private boolean mRestrictBackground; + private volatile boolean mScreenOn; + private volatile boolean mRestrictBackground; /** Defined network policies. */ private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap(); @@ -265,6 +272,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (mRestrictBackground) { updateRulesForRestrictBackgroundLocked(); + updateNotificationsLocked(); } } @@ -309,6 +317,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mContext.registerReceiver( mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); + // listen for restrict background changes from notifications + final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND); + mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler); + } private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { @@ -402,6 +414,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { }; /** + * Receiver that watches for {@link Notification} control of + * {@link #mRestrictBackground}. + */ + private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // on background handler thread, and verified MANAGE_NETWORK_POLICY + // permission above. + + setRestrictBackground(false); + } + }; + + /** * Observer that watches for {@link INetworkManagementService} alerts. */ private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { @@ -494,6 +520,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { notifyUnderLimitLocked(policy.template); } } + + // ongoing notification when restricting background data + if (mRestrictBackground) { + enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND); + } else { + cancelNotification(TAG_ALLOW_BACKGROUND); + } } /** @@ -614,16 +647,52 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } /** + * Show ongoing notification to reflect that {@link #mRestrictBackground} + * has been enabled. + */ + private void enqueueRestrictedNotification(String tag) { + final Resources res = mContext.getResources(); + final Notification.Builder builder = new Notification.Builder(mContext); + + final CharSequence title = res.getText(R.string.data_usage_restricted_title); + final CharSequence body = res.getString(R.string.data_usage_restricted_body); + + builder.setOnlyAlertOnce(true); + builder.setOngoing(true); + builder.setSmallIcon(R.drawable.ic_menu_info_details); + builder.setTicker(title); + builder.setContentTitle(title); + builder.setContentText(body); + + final Intent intent = buildAllowBackgroundDataIntent(); + builder.setContentIntent( + PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); + + // TODO: move to NotificationManager once we can mock it + try { + final String packageName = mContext.getPackageName(); + final int[] idReceived = new int[1]; + mNotifManager.enqueueNotificationWithTag(packageName, tag, + 0x0, builder.getNotification(), idReceived); + } catch (RemoteException e) { + Slog.w(TAG, "problem during enqueueNotification: " + e); + } + } + + /** * Cancel any notification for combined {@link NetworkPolicy} and specific * type, like {@link #TYPE_LIMIT}. */ private void cancelNotification(NetworkPolicy policy, int type) { - final String tag = buildNotificationTag(policy, type); + cancelNotification(buildNotificationTag(policy, type)); + } + private void cancelNotification(String tag) { // TODO: move to NotificationManager once we can mock it try { final String packageName = mContext.getPackageName(); - mNotifManager.cancelNotificationWithTag(packageName, tag, 0x0); + mNotifManager.cancelNotificationWithTag( + packageName, tag, 0x0); } catch (RemoteException e) { Slog.w(TAG, "problem during enqueueNotification: " + e); } @@ -731,15 +800,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED; final boolean hasWarning = policy.warningBytes != WARNING_DISABLED; - if (hasLimit || hasWarning) { - final long quotaBytes; - if (hasLimit) { - // remaining "quota" is based on usage in current cycle - quotaBytes = Math.max(0, policy.limitBytes - total); - } else { - // to track warning alert later, use a high quota - quotaBytes = Long.MAX_VALUE; - } + if (hasLimit) { + // remaining "quota" is based on usage in current cycle + final long quotaBytes = Math.max(0, policy.limitBytes - total); if (ifaces.length > 1) { // TODO: switch to shared quota once NMS supports @@ -754,16 +817,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } } - - if (hasWarning) { - final long alertBytes = Math.max(0, policy.warningBytes - total); - for (String iface : ifaces) { - removeInterfaceAlert(iface); - if (alertBytes > 0) { - setInterfaceAlert(iface, alertBytes); - } - } - } } // remove quota on any trailing interfaces @@ -839,11 +892,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mRestrictBackground = readBooleanAttribute( in, ATTR_RESTRICT_BACKGROUND); } else { - try { - mRestrictBackground = !mConnManager.getBackgroundDataSetting(); - } catch (RemoteException e) { - mRestrictBackground = false; - } + mRestrictBackground = false; } } else if (TAG_NETWORK_POLICY.equals(tag)) { @@ -879,6 +928,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } catch (FileNotFoundException e) { // missing policy is okay, probably first boot + upgradeLegacyBackgroundData(); } catch (IOException e) { Slog.e(TAG, "problem reading network stats", e); } catch (XmlPullParserException e) { @@ -888,6 +938,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + /** + * Upgrade legacy background data flags, notifying listeners of one last + * change to always-true. + */ + private void upgradeLegacyBackgroundData() { + mRestrictBackground = Settings.Secure.getInt( + mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1; + + // kick off one last broadcast if restricted + if (mRestrictBackground) { + final Intent broadcast = new Intent( + ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); + mContext.sendBroadcast(broadcast); + } + } + private void writePolicyLocked() { if (LOGV) Slog.v(TAG, "writePolicyLocked()"); @@ -1057,6 +1123,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { synchronized (mRulesLock) { mRestrictBackground = restrictBackground; updateRulesForRestrictBackgroundLocked(); + updateNotificationsLocked(); writePolicyLocked(); } } @@ -1420,6 +1487,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return telephony.getSubscriberId(); } + private static Intent buildAllowBackgroundDataIntent() { + return new Intent(ACTION_ALLOW_BACKGROUND); + } + private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) { final Intent intent = new Intent(); intent.setComponent(new ComponentName( diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 0425fc3..64eaecc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -133,6 +133,11 @@ sp<ISurface> Layer::createSurface() return sur; } +wp<IBinder> Layer::getSurfaceTextureBinder() const +{ + return mSurfaceTexture->asBinder(); +} + status_t Layer::setBuffers( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d3ddab4..5f0be80 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -74,6 +74,9 @@ public: virtual bool isProtected() const; virtual void onRemoved(); + // LayerBaseClient interface + virtual wp<IBinder> getSurfaceTextureBinder() const; + // only for debugging inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; } diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index e04c533..7bf73d9 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -544,6 +544,10 @@ wp<IBinder> LayerBaseClient::getSurfaceBinder() const { return mClientSurfaceBinder; } +wp<IBinder> LayerBaseClient::getSurfaceTextureBinder() const { + return 0; +} + void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const { LayerBase::dump(result, buffer, SIZE); diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index faf71dd..a3d3644 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -288,6 +288,7 @@ public: sp<ISurface> getSurface(); wp<IBinder> getSurfaceBinder() const; + virtual wp<IBinder> getSurfaceTextureBinder() const; virtual sp<LayerBaseClient> getLayerBaseClient() const { return const_cast<LayerBaseClient*>(this); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a68ab30..50afb3d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -353,9 +353,10 @@ void SurfaceFlinger::signalEvent() { mEventQueue.invalidate(); } -bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const { +bool SurfaceFlinger::authenticateSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) const { Mutex::Autolock _l(mStateLock); - sp<IBinder> surfBinder(surface->asBinder()); + sp<IBinder> surfaceTextureBinder(surfaceTexture->asBinder()); // Check the visible layer list for the ISurface const LayerVector& currentLayers = mCurrentState.layersSortedByZ; @@ -363,14 +364,17 @@ bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const { for (size_t i=0 ; i<count ; i++) { const sp<LayerBase>& layer(currentLayers[i]); sp<LayerBaseClient> lbc(layer->getLayerBaseClient()); - if (lbc != NULL && lbc->getSurfaceBinder() == surfBinder) { - return true; + if (lbc != NULL) { + wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder(); + if (lbcBinder == surfaceTextureBinder) { + return true; + } } } // Check the layers in the purgatory. This check is here so that if a - // Surface gets destroyed before all the clients are done using it, the - // error will not be reported as "surface XYZ is not authenticated", but + // SurfaceTexture gets destroyed before all the clients are done using it, + // the error will not be reported as "surface XYZ is not authenticated", but // will instead fail later on when the client tries to use the surface, // which should be reported as "surface XYZ returned an -ENODEV". The // purgatorized layers are no less authentic than the visible ones, so this @@ -379,8 +383,11 @@ bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const { for (size_t i=0 ; i<purgatorySize ; i++) { const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i)); sp<LayerBaseClient> lbc(layer->getLayerBaseClient()); - if (lbc != NULL && lbc->getSurfaceBinder() == surfBinder) { - return true; + if (lbc != NULL) { + wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder(); + if (lbcBinder == surfaceTextureBinder) { + return true; + } } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 89df0de..1738238 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -171,7 +171,7 @@ public: virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags); virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); - virtual bool authenticateSurface(const sp<ISurface>& surface) const; + virtual bool authenticateSurfaceTexture(const sp<ISurfaceTexture>& surface) const; virtual status_t captureScreen(DisplayID dpy, sp<IMemoryHeap>* heap, diff --git a/tests/BiDiTests/res/layout/basic.xml b/tests/BiDiTests/res/layout/basic.xml index e8f67a6..8a27213 100644 --- a/tests/BiDiTests/res/layout/basic.xml +++ b/tests/BiDiTests/res/layout/basic.xml @@ -34,6 +34,19 @@ android:textSize="32dip" /> + <TextView android:id="@+id/textview_default" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="32dip" + android:text="@string/textview_default_text" + /> + + <EditText android:id="@+id/edittext_default" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:textSize="32dip" + /> + <TextView android:id="@+id/textview_ltr" android:layout_height="wrap_content" android:layout_width="wrap_content" @@ -46,7 +59,6 @@ android:layout_width="match_parent" android:textSize="32dip" android:textDirection="ltr" - android:text="@string/url" /> <TextView android:id="@+id/textview_rtl" diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml index fde0ecf..b0809da 100644 --- a/tests/BiDiTests/res/values/strings.xml +++ b/tests/BiDiTests/res/values/strings.xml @@ -27,6 +27,7 @@ <string name="textview_text">This is a text for a TextView</string> <string name="textview_ltr_text">This is a text for a LTR TextView</string> <string name="textview_rtl_text">This is a text for a RTL TextView</string> + <string name="textview_default_text">This is a text for a default TextView</string> <string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string> <string name="normal_text">Normal String</string> <string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string> diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index daf53e0..178e7fd 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -1546,7 +1546,9 @@ int doPackage(Bundle* bundle) assets = new AaptAssets(); // Set up the resource gathering in assets if we're going to generate - // dependency files + // dependency files. Every time we encounter a resource while slurping + // the tree, we'll add it to these stores so we have full resource paths + // to write to a dependency file. if (bundle->getGenDependencies()) { sp<FilePathStore> resPathStore = new FilePathStore; assets->setFullResPaths(resPathStore); @@ -1577,15 +1579,20 @@ int doPackage(Bundle* bundle) goto bail; } + // If we've been asked to generate a dependency file, do that here if (bundle->getGenDependencies()) { + // If this is the packaging step, generate the dependency file next to + // the output apk (e.g. bin/resources.ap_.d) if (outputAPKFile) { dependencyFile = String8(outputAPKFile); - // Strip the extension and add new one - dependencyFile = dependencyFile.getBasePath(); + // Add the .d extension to the dependency file. dependencyFile.append(".d"); } else { + // Else if this is the R.java dependency generation step, + // generate the dependency file in the R.java package subdirectory + // e.g. gen/com/foo/app/R.java.d dependencyFile = String8(bundle->getRClassDir()); - dependencyFile.appendPath("R.d"); + dependencyFile.appendPath("R.java.d"); } // Make sure we have a clean dependency file to start with fp = fopen(dependencyFile, "w"); @@ -1595,13 +1602,18 @@ int doPackage(Bundle* bundle) // Write out R.java constants if (assets->getPackage() == assets->getSymbolsPrivatePackage()) { if (bundle->getCustomPackage() == NULL) { + // Write the R.java file into the appropriate class directory + // e.g. gen/com/foo/app/R.java err = writeResourceSymbols(bundle, assets, assets->getPackage(), true); - // Copy R.java for libraries + // If we have library files, we're going to write our R.java file into + // the appropriate class directory for those libraries as well. + // e.g. gen/com/foo/app/lib/R.java if (bundle->getExtraPackages() != NULL) { // Split on colon String8 libs(bundle->getExtraPackages()); char* packageString = strtok(libs.lockBuffer(libs.length()), ":"); while (packageString != NULL) { + // Write the R.java file out with the correct package name err = writeResourceSymbols(bundle, assets, String8(packageString), true); packageString = strtok(NULL, ":"); } @@ -1640,6 +1652,10 @@ int doPackage(Bundle* bundle) } } + // If we've been asked to generate a dependency file, we need to finish up here. + // the writeResourceSymbols and writeAPK functions have already written the target + // half of the dependency file, now we need to write the prerequisites. (files that + // the R.java file or .ap_ file depend on) if (bundle->getGenDependencies()) { // Now that writeResourceSymbols or writeAPK has taken care of writing // the targets to our dependency file, we'll write the prereqs @@ -1647,7 +1663,8 @@ int doPackage(Bundle* bundle) fprintf(fp, " : "); bool includeRaw = (outputAPKFile != NULL); err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); - // Also manually add the AndroidManifeset since it's a non-asset + // Also manually add the AndroidManifeset since it's not under res/ or assets/ + // and therefore was not added to our pathstores during slurping fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); fclose(fp); } diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp index c9f6870..1e3efde 100644 --- a/tools/aapt/Package.cpp +++ b/tools/aapt/Package.cpp @@ -177,12 +177,17 @@ status_t writeAPK(Bundle* bundle, const sp<AaptAssets>& assets, } } + // If we've been asked to generate a dependency file for the .ap_ package, + // do so here if (bundle->getGenDependencies()) { - // Add this file to the dependency file - String8 dependencyFile = outputFile.getBasePath(); + // The dependency file gets output to the same directory + // as the specified output file with an additional .d extension. + // e.g. bin/resources.ap_.d + String8 dependencyFile = outputFile; dependencyFile.append(".d"); FILE* fp = fopen(dependencyFile.string(), "a"); + // Add this file to the dependency file fprintf(fp, "%s \\\n", outputFile.string()); fclose(fp); } diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index cb6484f..2e796a2 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -1958,10 +1958,12 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets, } fclose(fp); + // If we were asked to generate a dependency file, we'll go ahead and add this R.java + // as a target in the dependency file right next to it. if (bundle->getGenDependencies()) { // Add this R.java to the dependency file String8 dependencyFile(bundle->getRClassDir()); - dependencyFile.appendPath("R.d"); + dependencyFile.appendPath("R.java.d"); fp = fopen(dependencyFile.string(), "a"); fprintf(fp,"%s \\\n", dest.string()); |
