Merge "Change TrafficStats to a new JNI implementation." into froyo
diff --git a/Android.mk b/Android.mk
index cecc26a..10b6d67 100644
--- a/Android.mk
+++ b/Android.mk
@@ -117,6 +117,7 @@
core/java/android/hardware/ISensorService.aidl \
core/java/android/net/IConnectivityManager.aidl \
core/java/android/net/INetworkManagementEventObserver.aidl \
+ core/java/android/net/IThrottleManager.aidl \
core/java/android/os/IMessenger.aidl \
core/java/android/os/storage/IMountService.aidl \
core/java/android/os/storage/IMountServiceListener.aidl \
diff --git a/api/current.xml b/api/current.xml
index e231528..58b9c17 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -34,17 +34,6 @@
visibility="public"
>
</constructor>
-<field name="ACCESS_CACHE_FILESYSTEM"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.permission.ACCESS_CACHE_FILESYSTEM""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="ACCESS_CHECKIN_PROPERTIES"
type="java.lang.String"
transient="false"
@@ -716,17 +705,6 @@
visibility="public"
>
</field>
-<field name="MOVE_PACKAGE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.permission.MOVE_PACKAGE""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="PERSISTENT_ACTIVITY"
type="java.lang.String"
transient="false"
@@ -71656,7 +71634,7 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
-<method name="setZoomCallback"
+<method name="setZoomChangeListener"
return="void"
abstract="false"
native="false"
@@ -71666,7 +71644,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="cb" type="android.hardware.Camera.ZoomCallback">
+<parameter name="listener" type="android.hardware.Camera.OnZoomChangeListener">
</parameter>
</method>
<method name="startPreview"
@@ -71831,6 +71809,31 @@
</parameter>
</method>
</interface>
+<interface name="Camera.OnZoomChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onZoomChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="zoomValue" type="int">
+</parameter>
+<parameter name="stopped" type="boolean">
+</parameter>
+<parameter name="camera" type="android.hardware.Camera">
+</parameter>
+</method>
+</interface>
<class name="Camera.Parameters"
extends="java.lang.Object"
abstract="false"
@@ -73255,31 +73258,6 @@
>
</field>
</class>
-<interface name="Camera.ZoomCallback"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onZoomUpdate"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="zoomValue" type="int">
-</parameter>
-<parameter name="stopped" type="boolean">
-</parameter>
-<parameter name="camera" type="android.hardware.Camera">
-</parameter>
-</method>
-</interface>
<class name="GeomagneticField"
extends="java.lang.Object"
abstract="false"
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 659d70f..9b8b0ac 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -16,6 +16,8 @@
package com.android.commands.pm;
+import com.android.internal.content.PackageHelper;
+
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.FeatureInfo;
@@ -33,6 +35,7 @@
import android.net.Uri;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.provider.Settings;
import java.io.File;
import java.lang.reflect.Field;
@@ -107,6 +110,16 @@
return;
}
+ if ("setInstallLocation".equals(op)) {
+ runSetInstallLocation();
+ return;
+ }
+
+ if ("getInstallLocation".equals(op)) {
+ runGetInstallLocation();
+ return;
+ }
+
try {
if (args.length == 1) {
if (args[0].equalsIgnoreCase("-l")) {
@@ -575,6 +588,51 @@
return Integer.toString(result);
}
+ private void runSetInstallLocation() {
+ int loc;
+
+ String arg = nextArg();
+ if (arg == null) {
+ System.err.println("Error: no install location specified.");
+ showUsage();
+ return;
+ }
+ try {
+ loc = Integer.parseInt(arg);
+ } catch (NumberFormatException e) {
+ System.err.println("Error: install location has to be a number.");
+ showUsage();
+ return;
+ }
+ try {
+ if (!mPm.setInstallLocation(loc)) {
+ System.err.println("Error: install location has to be a number.");
+ showUsage();
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
+ private void runGetInstallLocation() {
+ try {
+ int loc = mPm.getInstallLocation();
+ String locStr = "invalid";
+ if (loc == PackageHelper.APP_INSTALL_AUTO) {
+ locStr = "auto";
+ } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
+ locStr = "internal";
+ } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
+ locStr = "external";
+ }
+ System.out.println(loc + "[" + locStr + "]");
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
private void runInstall() {
int installFlags = 0;
String installerPackageName = null;
@@ -832,6 +890,7 @@
System.err.println(" pm uninstall [-k] PACKAGE");
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
System.err.println(" pm disable PACKAGE_OR_COMPONENT");
+ System.err.println(" pm setInstallLocation [0/auto] [1/internal] [2/external]");
System.err.println("");
System.err.println("The list packages command prints all packages. Options:");
System.err.println(" -f: see their associated file.");
@@ -867,10 +926,17 @@
System.err.println(" -k: keep the data and cache directories around.");
System.err.println("after the package removal.");
System.err.println("");
- System.err.println("The mountsd command simulates mounting/unmounting sdcard.Options:");
- System.err.println(" -m: true or false.");
- System.err.println("");
System.err.println("The enable and disable commands change the enabled state of");
System.err.println("a given package or component (written as \"package/class\").");
+ System.err.println("");
+ System.err.println("The getInstallLocation command gets the current install location");
+ System.err.println(" 0 [auto]: Let system decide the best location");
+ System.err.println(" 1 [internal]: Install on internal device storage");
+ System.err.println(" 2 [external]: Install on external media");
+ System.err.println("");
+ System.err.println("The setInstallLocation command changes the default install location");
+ System.err.println(" 0 [auto]: Let system decide the best location");
+ System.err.println(" 1 [internal]: Install on internal device storage");
+ System.err.println(" 2 [external]: Install on external media");
}
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b07b690..950f34f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1482,8 +1482,9 @@
mPackageInfo = packageInfo;
mResources = mPackageInfo.getResources(mainThread);
- if (container != null && container.getCompatibilityInfo().applicationScale !=
- mResources.getCompatibilityInfo().applicationScale) {
+ if (mResources != null && container != null
+ && container.getCompatibilityInfo().applicationScale !=
+ mResources.getCompatibilityInfo().applicationScale) {
if (DEBUG) {
Log.d(TAG, "loaded context has different scaling. Using container's" +
" compatiblity info:" + container.getDisplayMetrics());
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 1cb2353..d114ecc 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1307,7 +1307,7 @@
String blockingPackage = ActivityThread.currentPackageName();
EventLog.writeEvent(
- EventLogTags.CONTENT_QUERY_OPERATION,
+ EventLogTags.CONTENT_QUERY_SAMPLE,
uri.toString(),
projectionBuffer.toString(),
selection != null ? selection : "",
@@ -1329,7 +1329,7 @@
}
String blockingPackage = ActivityThread.currentPackageName();
EventLog.writeEvent(
- EventLogTags.CONTENT_UPDATE_OPERATION,
+ EventLogTags.CONTENT_UPDATE_SAMPLE,
uri.toString(),
operation,
selection != null ? selection : "",
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3a2aa55..30822d4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1398,7 +1398,7 @@
* @see android.os.Vibrator
*/
public static final String VIBRATOR_SERVICE = "vibrator";
-
+
/**
* Use with {@link #getSystemService} to retrieve a {@link
* android.app.StatusBarManager} for interacting with the status bar.
@@ -1421,6 +1421,17 @@
/**
* Use with {@link #getSystemService} to retrieve a {@link
+ * android.net.ThrottleManager} for handling management of
+ * throttling.
+ *
+ * @hide
+ * @see #getSystemService
+ * @see android.net.ThrottleManager
+ */
+ public static final String THROTTLE_SERVICE = "throttle";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a {@link
* android.net.NetworkManagementService} for handling management of
* system network services
*
diff --git a/core/java/android/content/EventLogTags.logtags b/core/java/android/content/EventLogTags.logtags
index 0a8c9b0..21ea90a 100644
--- a/core/java/android/content/EventLogTags.logtags
+++ b/core/java/android/content/EventLogTags.logtags
@@ -2,6 +2,6 @@
option java_package android.content;
-52002 content_query_operation (uri|3),(projection|3),(selection|3),(sortorder|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
-52003 content_update_operation (uri|3),(operation|3),(selection|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
-52004 binder_operation (descriptor|3),(method_num|1|5),(time|1|3),(blocking_package|3),(sample_percent|1|6)
+52002 content_query_sample (uri|3),(projection|3),(selection|3),(sortorder|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
+52003 content_update_sample (uri|3),(operation|3),(selection|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
+52004 binder_sample (descriptor|3),(method_num|1|5),(time|1|3),(blocking_package|3),(sample_percent|1|6)
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index f90ef63..9939478 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -316,4 +316,7 @@
void movePackage(String packageName, IPackageMoveObserver observer, int flags);
boolean addPermissionAsync(in PermissionInfo info);
+
+ boolean setInstallLocation(int loc);
+ int getInstallLocation();
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index abebdeb9..2495619 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -78,7 +78,7 @@
private PreviewCallback mPreviewCallback;
private PictureCallback mPostviewCallback;
private AutoFocusCallback mAutoFocusCallback;
- private ZoomCallback mZoomCallback;
+ private OnZoomChangeListener mZoomListener;
private ErrorCallback mErrorCallback;
private boolean mOneShot;
private boolean mWithBuffer;
@@ -96,7 +96,7 @@
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
- mZoomCallback = null;
+ mZoomListener = null;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
@@ -270,16 +270,18 @@
}
/**
- * Adds a pre-allocated buffer to the callback buffer queue. Applications
- * can add one or more buffers to the queue. When a preview frame arrives
- * and there is still available buffer, buffer will be filled and it is
- * removed from the queue. Then preview callback is invoked with the buffer.
- * If a frame arrives and there is no buffer left, the frame is discarded.
- * Applications should add the buffers back when they finish the processing.
+ * Adds a pre-allocated buffer to the preview callback buffer queue.
+ * Applications can add one or more buffers to the queue. When a preview
+ * frame arrives and there is still available buffer, buffer will be filled
+ * and it is removed from the queue. Then preview callback is invoked with
+ * the buffer. If a frame arrives and there is no buffer left, the frame is
+ * discarded. Applications should add the buffers back when they finish the
+ * processing.
*
- * Preview width and height can be determined from getPreviewSize, and bitsPerPixel can be
- * found from {@link android.hardware.Camera.Parameters#getPreviewFormat()}
- * and {@link android.graphics.ImageFormat#getBitsPerPixel(int)}.
+ * The image format of the callback buffer can be read from {@link
+ * android.hardware.Camera.Parameters#getPreviewFormat()}. bitsPerPixel can
+ * be read from {@link android.graphics.ImageFormat#getBitsPerPixel(int)}.
+ * Preview width and height can be determined from getPreviewSize.
*
* Alternatively, a buffer from a previous callback may be passed in or used
* to determine the size of new preview frame buffers.
@@ -350,8 +352,8 @@
return;
case CAMERA_MSG_ZOOM:
- if (mZoomCallback != null) {
- mZoomCallback.onZoomUpdate(msg.arg1, msg.arg2 != 0, mCamera);
+ if (mZoomListener != null) {
+ mZoomListener.onZoomChange(msg.arg1, msg.arg2 != 0, mCamera);
}
return;
@@ -526,15 +528,15 @@
}
/**
- * Zooms to the requested value smoothly. Driver will generate {@link
- * ZoomCallback} for the zoom value and whether zoom is stopped at the
- * time. For example, suppose the current zoom is 0 and startSmoothZoom is
- * called with value 3. Three ZoomCallback will be generated with zoom value
- * 1, 2, and 3. The applications can call {@link #stopSmoothZoom} to stop
- * the zoom earlier. The applications should not call startSmoothZoom again
- * or change the zoom value before zoom stops. If the passing zoom value
- * equals to the current zoom value, no zoom callback will be generated.
- * This method is supported if {@link
+ * Zooms to the requested value smoothly. Driver will notify {@link
+ * OnZoomChangeListener} of the zoom value and whether zoom is stopped at
+ * the time. For example, suppose the current zoom is 0 and startSmoothZoom
+ * is called with value 3. Method onZoomChange will be called three times
+ * with zoom value 1, 2, and 3. The applications can call {@link
+ * #stopSmoothZoom} to stop the zoom earlier. The applications should not
+ * call startSmoothZoom again or change the zoom value before zoom stops. If
+ * the passing zoom value equals to the current zoom value, no zoom callback
+ * will be generated. This method is supported if {@link
* android.hardware.Camera.Parameters#isSmoothZoomSupported} is true.
*
* @param value zoom value. The valid range is 0 to {@link
@@ -546,8 +548,8 @@
/**
* Stops the smooth zoom. The applications should wait for the {@link
- * ZoomCallback} to know when the zoom is actually stopped. This method is
- * supported if {@link
+ * OnZoomChangeListener} to know when the zoom is actually stopped. This
+ * method is supported if {@link
* android.hardware.Camera.Parameters#isSmoothZoomSupported} is true.
*
* @throws RuntimeException if the method fails.
@@ -570,35 +572,34 @@
public native final void setDisplayOrientation(int degrees);
/**
- * Handles the zoom callback.
- *
+ * Interface for a callback to be invoked when zoom value changes.
*/
- public interface ZoomCallback
+ public interface OnZoomChangeListener
{
/**
- * Callback for zoom updates
+ * Called when the zoom value has changed.
*
* @param zoomValue the current zoom value. In smooth zoom mode, camera
- * generates this callback for every new zoom value.
+ * calls this for every new zoom value.
* @param stopped whether smooth zoom is stopped. If the value is true,
* this is the last zoom update for the application.
*
* @param camera the Camera service object
* @see #startSmoothZoom(int)
*/
- void onZoomUpdate(int zoomValue, boolean stopped, Camera camera);
+ void onZoomChange(int zoomValue, boolean stopped, Camera camera);
};
/**
- * Registers a callback to be invoked when the zoom value is updated by the
+ * Registers a listener to be notified when the zoom value is updated by the
* camera driver during smooth zoom.
*
- * @param cb the callback to run
+ * @param listener the listener to notify
* @see #startSmoothZoom(int)
*/
- public final void setZoomCallback(ZoomCallback cb)
+ public final void setZoomChangeListener(OnZoomChangeListener listener)
{
- mZoomCallback = cb;
+ mZoomListener = listener;
}
// These match the enum in include/ui/Camera.h
@@ -992,7 +993,7 @@
/**
* Gets the supported preview sizes.
*
- * @return a List of Size object. This method will always return a list
+ * @return a list of Size object. This method will always return a list
* with at least one element.
*/
public List<Size> getSupportedPreviewSizes() {
@@ -1027,7 +1028,7 @@
/**
* Gets the supported jpeg thumbnail sizes.
*
- * @return a List of Size object. This method will always return a list
+ * @return a list of Size object. This method will always return a list
* with at least two elements. Size 0,0 (no thumbnail) is always
* supported.
*/
@@ -1098,8 +1099,8 @@
/**
* Gets the supported preview frame rates.
*
- * @return a List of Integer objects (preview frame rates). null if
- * preview frame rate setting is not supported.
+ * @return a list of supported preview frame rates. null if preview
+ * frame rate setting is not supported.
*/
public List<Integer> getSupportedPreviewFrameRates() {
String str = get(KEY_PREVIEW_FRAME_RATE + SUPPORTED_VALUES_SUFFIX);
@@ -1130,11 +1131,11 @@
}
/**
- * Returns the image format for preview pictures got from
+ * Returns the image format for preview frames got from
* {@link PreviewCallback}.
*
- * @return the {@link android.graphics.ImageFormat} int representing
- * the preview picture format.
+ * @return the preview format.
+ * @see android.graphics.ImageFormat
*/
public int getPreviewFormat() {
return pixelFormatForCameraFormat(get(KEY_PREVIEW_FORMAT));
@@ -1143,8 +1144,9 @@
/**
* Gets the supported preview formats.
*
- * @return a List of Integer objects. This method will always return a
- * list with at least one element.
+ * @return a list of supported preview formats. This method will always
+ * return a list with at least one element.
+ * @see android.graphics.ImageFormat
*/
public List<Integer> getSupportedPreviewFormats() {
String str = get(KEY_PREVIEW_FORMAT + SUPPORTED_VALUES_SUFFIX);
@@ -1182,8 +1184,8 @@
/**
* Gets the supported picture sizes.
*
- * @return a List of Size objects. This method will always return a list
- * with at least one element.
+ * @return a list of supported picture sizes. This method will always
+ * return a list with at least one element.
*/
public List<Size> getSupportedPictureSizes() {
String str = get(KEY_PICTURE_SIZE + SUPPORTED_VALUES_SUFFIX);
@@ -1212,7 +1214,8 @@
/**
* Returns the image format for pictures.
*
- * @return the ImageFormat int representing the picture format
+ * @return the picture format
+ * @see android.graphics.ImageFormat
*/
public int getPictureFormat() {
return pixelFormatForCameraFormat(get(KEY_PICTURE_FORMAT));
@@ -1221,8 +1224,9 @@
/**
* Gets the supported picture formats.
*
- * @return a List of Integer objects (values are ImageFormat.XXX). This
- * method will always return a list with at least one element.
+ * @return supported picture formats. This method will always return a
+ * list with at least one element.
+ * @see android.graphics.ImageFormat
*/
public List<Integer> getSupportedPictureFormats() {
String str = get(KEY_PICTURE_FORMAT + SUPPORTED_VALUES_SUFFIX);
@@ -1361,8 +1365,17 @@
/**
* Gets the current white balance setting.
*
- * @return one of WHITE_BALANCE_XXX string constant. null if white
- * balance setting is not supported.
+ * @return current white balance. null if white balance setting is not
+ * supported.
+ * @see #WHITE_BALANCE_AUTO
+ * @see #WHITE_BALANCE_INCANDESCENT
+ * @see #WHITE_BALANCE_FLUORESCENT
+ * @see #WHITE_BALANCE_WARM_FLUORESCENT
+ * @see #WHITE_BALANCE_DAYLIGHT
+ * @see #WHITE_BALANCE_CLOUDY_DAYLIGHT
+ * @see #WHITE_BALANCE_TWILIGHT
+ * @see #WHITE_BALANCE_SHADE
+ *
*/
public String getWhiteBalance() {
return get(KEY_WHITE_BALANCE);
@@ -1371,7 +1384,8 @@
/**
* Sets the white balance.
*
- * @param value WHITE_BALANCE_XXX string constant.
+ * @param value new white balance.
+ * @see #getWhiteBalance()
*/
public void setWhiteBalance(String value) {
set(KEY_WHITE_BALANCE, value);
@@ -1380,8 +1394,9 @@
/**
* Gets the supported white balance.
*
- * @return a List of WHITE_BALANCE_XXX string constants. null if white
- * balance setting is not supported.
+ * @return a list of supported white balance. null if white balance
+ * setting is not supported.
+ * @see #getWhiteBalance()
*/
public List<String> getSupportedWhiteBalance() {
String str = get(KEY_WHITE_BALANCE + SUPPORTED_VALUES_SUFFIX);
@@ -1391,8 +1406,17 @@
/**
* Gets the current color effect setting.
*
- * @return one of EFFECT_XXX string constant. null if color effect
+ * @return current color effect. null if color effect
* setting is not supported.
+ * @see #EFFECT_NONE
+ * @see #EFFECT_MONO
+ * @see #EFFECT_NEGATIVE
+ * @see #EFFECT_SOLARIZE
+ * @see #EFFECT_SEPIA
+ * @see #EFFECT_POSTERIZE
+ * @see #EFFECT_WHITEBOARD
+ * @see #EFFECT_BLACKBOARD
+ * @see #EFFECT_AQUA
*/
public String getColorEffect() {
return get(KEY_EFFECT);
@@ -1401,7 +1425,8 @@
/**
* Sets the current color effect setting.
*
- * @param value EFFECT_XXX string constants.
+ * @param value new color effect.
+ * @see #getColorEffect()
*/
public void setColorEffect(String value) {
set(KEY_EFFECT, value);
@@ -1410,8 +1435,9 @@
/**
* Gets the supported color effects.
*
- * @return a List of EFFECT_XXX string constants. null if color effect
+ * @return a list of supported color effects. null if color effect
* setting is not supported.
+ * @see #getColorEffect()
*/
public List<String> getSupportedColorEffects() {
String str = get(KEY_EFFECT + SUPPORTED_VALUES_SUFFIX);
@@ -1422,8 +1448,12 @@
/**
* Gets the current antibanding setting.
*
- * @return one of ANTIBANDING_XXX string constant. null if antibanding
- * setting is not supported.
+ * @return current antibanding. null if antibanding setting is not
+ * supported.
+ * @see #ANTIBANDING_AUTO
+ * @see #ANTIBANDING_50HZ
+ * @see #ANTIBANDING_60HZ
+ * @see #ANTIBANDING_OFF
*/
public String getAntibanding() {
return get(KEY_ANTIBANDING);
@@ -1432,7 +1462,8 @@
/**
* Sets the antibanding.
*
- * @param antibanding ANTIBANDING_XXX string constant.
+ * @param antibanding new antibanding value.
+ * @see #getAntibanding()
*/
public void setAntibanding(String antibanding) {
set(KEY_ANTIBANDING, antibanding);
@@ -1441,8 +1472,9 @@
/**
* Gets the supported antibanding values.
*
- * @return a List of ANTIBANDING_XXX string constants. null if
- * antibanding setting is not supported.
+ * @return a list of supported antibanding values. null if antibanding
+ * setting is not supported.
+ * @see #getAntibanding()
*/
public List<String> getSupportedAntibanding() {
String str = get(KEY_ANTIBANDING + SUPPORTED_VALUES_SUFFIX);
@@ -1454,6 +1486,21 @@
*
* @return one of SCENE_MODE_XXX string constant. null if scene mode
* setting is not supported.
+ * @see #SCENE_MODE_AUTO
+ * @see #SCENE_MODE_ACTION
+ * @see #SCENE_MODE_PORTRAIT
+ * @see #SCENE_MODE_LANDSCAPE
+ * @see #SCENE_MODE_NIGHT
+ * @see #SCENE_MODE_NIGHT_PORTRAIT
+ * @see #SCENE_MODE_THEATRE
+ * @see #SCENE_MODE_BEACH
+ * @see #SCENE_MODE_SNOW
+ * @see #SCENE_MODE_SUNSET
+ * @see #SCENE_MODE_STEADYPHOTO
+ * @see #SCENE_MODE_FIREWORKS
+ * @see #SCENE_MODE_SPORTS
+ * @see #SCENE_MODE_PARTY
+ * @see #SCENE_MODE_CANDLELIGHT
*/
public String getSceneMode() {
return get(KEY_SCENE_MODE);
@@ -1466,7 +1513,8 @@
* applications should call getParameters to know if some parameters are
* changed.
*
- * @param value SCENE_MODE_XXX string constants.
+ * @param value scene mode.
+ * @see #getSceneMode()
*/
public void setSceneMode(String value) {
set(KEY_SCENE_MODE, value);
@@ -1475,8 +1523,9 @@
/**
* Gets the supported scene modes.
*
- * @return a List of SCENE_MODE_XXX string constant. null if scene mode
- * setting is not supported.
+ * @return a list of supported scene modes. null if scene mode setting
+ * is not supported.
+ * @see #getSceneMode()
*/
public List<String> getSupportedSceneModes() {
String str = get(KEY_SCENE_MODE + SUPPORTED_VALUES_SUFFIX);
@@ -1486,8 +1535,13 @@
/**
* Gets the current flash mode setting.
*
- * @return one of FLASH_MODE_XXX string constant. null if flash mode
- * setting is not supported.
+ * @return current flash mode. null if flash mode setting is not
+ * supported.
+ * @see #FLASH_MODE_OFF
+ * @see #FLASH_MODE_AUTO
+ * @see #FLASH_MODE_ON
+ * @see #FLASH_MODE_RED_EYE
+ * @see #FLASH_MODE_TORCH
*/
public String getFlashMode() {
return get(KEY_FLASH_MODE);
@@ -1496,7 +1550,8 @@
/**
* Sets the flash mode.
*
- * @param value FLASH_MODE_XXX string constants.
+ * @param value flash mode.
+ * @see #getFlashMode()
*/
public void setFlashMode(String value) {
set(KEY_FLASH_MODE, value);
@@ -1505,8 +1560,9 @@
/**
* Gets the supported flash modes.
*
- * @return a List of FLASH_MODE_XXX string constants. null if flash mode
- * setting is not supported.
+ * @return a list of supported flash modes. null if flash mode setting
+ * is not supported.
+ * @see #getFlashMode()
*/
public List<String> getSupportedFlashModes() {
String str = get(KEY_FLASH_MODE + SUPPORTED_VALUES_SUFFIX);
@@ -1516,11 +1572,15 @@
/**
* Gets the current focus mode setting.
*
- * @return one of FOCUS_MODE_XXX string constant. If the camera does not
- * support auto-focus, this should return {@link
- * #FOCUS_MODE_FIXED}. If the focus mode is not FOCUS_MODE_FIXED
- * or {@link #FOCUS_MODE_INFINITY}, applications should call
- * {@link #autoFocus(AutoFocusCallback)} to start the focus.
+ * @return current focus mode. If the camera does not support
+ * auto-focus, this should return {@link #FOCUS_MODE_FIXED}. If
+ * the focus mode is not FOCUS_MODE_FIXED or {@link
+ * #FOCUS_MODE_INFINITY}, applications should call {@link
+ * #autoFocus(AutoFocusCallback)} to start the focus.
+ * @see #FOCUS_MODE_AUTO
+ * @see #FOCUS_MODE_INFINITY
+ * @see #FOCUS_MODE_MACRO
+ * @see #FOCUS_MODE_FIXED
*/
public String getFocusMode() {
return get(KEY_FOCUS_MODE);
@@ -1529,7 +1589,8 @@
/**
* Sets the focus mode.
*
- * @param value FOCUS_MODE_XXX string constants.
+ * @param value focus mode.
+ * @see #getFocusMode()
*/
public void setFocusMode(String value) {
set(KEY_FOCUS_MODE, value);
@@ -1538,8 +1599,9 @@
/**
* Gets the supported focus modes.
*
- * @return a List of FOCUS_MODE_XXX string constants. This method will
- * always return a list with at least one element.
+ * @return a list of supported focus modes. This method will always
+ * return a list with at least one element.
+ * @see #getFocusMode()
*/
public List<String> getSupportedFocusModes() {
String str = get(KEY_FOCUS_MODE + SUPPORTED_VALUES_SUFFIX);
diff --git a/core/java/android/net/IThrottleManager.aidl b/core/java/android/net/IThrottleManager.aidl
new file mode 100644
index 0000000..298de6e
--- /dev/null
+++ b/core/java/android/net/IThrottleManager.aidl
@@ -0,0 +1,38 @@
+/**
+ * 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.
+ */
+
+package android.net;
+
+import android.os.IBinder;
+
+/**
+ * Interface that answers queries about data transfer amounts and throttling
+ */
+/** {@hide} */
+interface IThrottleManager
+{
+ long getByteCount(String iface, int dir, int period, int ago);
+
+ int getThrottle(String iface);
+
+ long getResetTime(String iface);
+
+ long getPeriodStartTime(String iface);
+
+ long getCliffThreshold(String iface, int cliff);
+
+ int getCliffLevel(String iface, int cliff);
+}
diff --git a/core/java/android/net/ThrottleManager.java b/core/java/android/net/ThrottleManager.java
new file mode 100644
index 0000000..0500f6f
--- /dev/null
+++ b/core/java/android/net/ThrottleManager.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2008 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.net;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.os.Binder;
+import android.os.RemoteException;
+
+/**
+ * Class that handles throttling. It provides read/write numbers per interface
+ * and methods to apply throttled rates.
+ * {@hide}
+ */
+public class ThrottleManager
+{
+ /**
+ * Broadcast each polling period to indicate new data counts.
+ *
+ * Includes four extras:
+ * EXTRA_CYCLE_READ - a long of the read bytecount for the current cycle
+ * EXTRA_CYCLE_WRITE -a long of the write bytecount for the current cycle
+ * EXTRA_CYLCE_START -a long of MS for the cycle start time
+ * EXTRA_CYCLE_END -a long of MS for the cycle stop time
+ * {@hide}
+ */
+ public static final String THROTTLE_POLL_ACTION = "android.net.thrott.POLL_ACTION";
+ /**
+ * The lookup key for a long for the read bytecount for this period. Retrieve with
+ * {@link android.content.Intent#getLongExtra(String)}.
+ * {@hide}
+ */
+ public static final String EXTRA_CYCLE_READ = "cycleRead";
+ /**
+ * contains a long of the number of bytes written in the cycle
+ * {@hide}
+ */
+ public static final String EXTRA_CYCLE_WRITE = "cycleWrite";
+ /**
+ * contains a long of the number of bytes read in the cycle
+ * {@hide}
+ */
+ public static final String EXTRA_CYCLE_START = "cycleStart";
+ /**
+ * contains a long of the ms since 1970 used to init a calendar, etc for the end
+ * of the cycle
+ * {@hide}
+ */
+ public static final String EXTRA_CYCLE_END = "cycleEnd";
+
+ /**
+ * Broadcast when the thottle level changes.
+ * {@hide}
+ */
+ public static final String THROTTLE_ACTION = "android.net.thrott.THROTTLE_ACTION";
+ /**
+ * int of the current bandwidth in TODO
+ * {@hide}
+ */
+ public static final String EXTRA_THROTTLE_LEVEL = "level";
+
+ // {@hide}
+ public static final int DIRECTION_TX = 0;
+ // {@hide}
+ public static final int DIRECTION_RX = 1;
+
+ // {@hide}
+ public static final int PERIOD_CYCLE = 0;
+ // {@hide}
+ public static final int PERIOD_YEAR = 1;
+ // {@hide}
+ public static final int PERIOD_MONTH = 2;
+ // {@hide}
+ public static final int PERIOD_WEEK = 3;
+ // @hide
+ public static final int PERIOD_7DAY = 4;
+ // @hide
+ public static final int PERIOD_DAY = 5;
+ // @hide
+ public static final int PERIOD_24HOUR = 6;
+ // @hide
+ public static final int PERIOD_HOUR = 7;
+ // @hide
+ public static final int PERIOD_60MIN = 8;
+ // @hide
+ public static final int PERIOD_MINUTE = 9;
+ // @hide
+ public static final int PERIOD_60SEC = 10;
+ // @hide
+ public static final int PERIOD_SECOND = 11;
+
+ /**
+ * returns a long of the ms from the epoch to the time the current cycle ends for the
+ * named interface
+ * {@hide}
+ */
+ public long getResetTime(String iface) {
+ try {
+ return mService.getResetTime(iface);
+ } catch (RemoteException e) {
+ return -1;
+ }
+ }
+
+ /**
+ * returns a long of the ms from the epoch to the time the current cycle started for the
+ * named interface
+ * {@hide}
+ */
+ public long getPeriodStartTime(String iface) {
+ try {
+ return mService.getPeriodStartTime(iface);
+ } catch (RemoteException e) {
+ return -1;
+ }
+ }
+
+ /**
+ * returns a long of the byte count either read or written on the named interface
+ * for the period described. Direction is either DIRECTION_RX or DIRECTION_TX and
+ * period may only be PERIOD_CYCLE for the current cycle (other periods may be supported
+ * in the future). Ago indicates the number of periods in the past to lookup - 0 means
+ * the current period, 1 is the last one, 2 was two periods ago..
+ * {@hide}
+ */
+ public long getByteCount(String iface, int direction, int period, int ago) {
+ try {
+ return mService.getByteCount(iface, direction, period, ago);
+ } catch (RemoteException e) {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the number of bytes read+written after which a particular cliff
+ * takes effect on the named iface. Currently only cliff #0 is supported (1 step)
+ * {@hide}
+ */
+ public long getCliffThreshold(String iface, int cliff) {
+ try {
+ return mService.getCliffThreshold(iface, cliff);
+ } catch (RemoteException e) {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the thottling bandwidth (bps) for a given cliff # on the named iface.
+ * only cliff #0 is currently supported.
+ * {@hide}
+ */
+ public int getCliffLevel(String iface, int cliff) {
+ try {
+ return mService.getCliffLevel(iface, cliff);
+ } catch (RemoteException e) {
+ return -1;
+ }
+ }
+
+ private IThrottleManager mService;
+
+ /**
+ * Don't allow use of default constructor.
+ */
+ @SuppressWarnings({"UnusedDeclaration"})
+ private ThrottleManager() {
+ }
+
+ /**
+ * {@hide}
+ */
+ public ThrottleManager(IThrottleManager service) {
+ if (service == null) {
+ throw new IllegalArgumentException(
+ "ThrottleManager() cannot be constructed with null service");
+ }
+ mService = service;
+ }
+}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index f7e7d39..812391c 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -166,9 +166,11 @@
* Standard directory in which to place files that have been downloaded by
* the user. Note that this is primarily a convention for the top-level
* public directory, you are free to download files anywhere in your own
- * private directories.
+ * private directories. Also note that though the constant here is
+ * named DIRECTORY_DOWNLOADS (plural), the actual file name is non-plural for
+ * backwards compatibility reasons.
*/
- public static String DIRECTORY_DOWNLOADS = "Downloads";
+ public static String DIRECTORY_DOWNLOADS = "Download";
/**
* The traditional location for pictures and videos when mounting the
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b8e5747..eb14815 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1611,21 +1611,6 @@
public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
/**
- * Let user pick default install location.
- * @hide
- */
- public static final String SET_INSTALL_LOCATION = "set_install_location";
-
- /**
- * Default install location value.
- * 0 = auto, let system decide
- * 1 = internal
- * 2 = sdcard
- * @hide
- */
- public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
-
- /**
* Show pointer location on screen?
* 0 = no
* 1 = yes
@@ -3295,7 +3280,58 @@
* @hide
*/
public static final String UI_NIGHT_MODE = "ui_night_mode";
-
+
+ /**
+ * Let user pick default install location.
+ * @hide
+ */
+ public static final String SET_INSTALL_LOCATION = "set_install_location";
+
+ /**
+ * Default install location value.
+ * 0 = auto, let system decide
+ * 1 = internal
+ * 2 = sdcard
+ * @hide
+ */
+ public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
+
+ /**
+ * The bandwidth throttle polling freqency in seconds
+ * @hide
+ */
+ public static final String THROTTLE_POLLING_SEC = "throttle_polling_sec";
+
+ /**
+ * The bandwidth throttle threshold (long)
+ * @hide
+ */
+ public static final String THROTTLE_THRESHOLD = "throttle_threshold";
+
+ /**
+ * The bandwidth throttle value (kbps)
+ * @hide
+ */
+ public static final String THROTTLE_VALUE = "throttle_value";
+
+ /**
+ * The bandwidth throttle reset calendar day (1-28)
+ * @hide
+ */
+ public static final String THROTTLE_RESET_DAY = "throttle_reset_day";
+
+ /**
+ * The throttling notifications we should send
+ * @hide
+ */
+ public static final String THROTTLE_NOTIFICATION_TYPE = "throttle_notification_type";
+
+ /**
+ * The interface we throttle
+ * @hide
+ */
+ public static final String THROTTLE_IFACE = "throttle_iface";
+
/**
* @hide
*/
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 096ad39..08cd2f0 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -313,6 +313,8 @@
"Need BLUETOOTH_ADMIN permission");
if (DBG) log("connectSink(" + device + ")");
+ if (!mBluetoothService.isEnabled()) return false;
+
// ignore if there are any active sinks
if (lookupSinksMatchingStates(new int[] {
BluetoothA2dp.STATE_CONNECTING,
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 42e1539..eee8025 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -129,9 +129,10 @@
// is invoked.
mTimer.cancel();
mTimer = null;
- mCurrentProxy.playbackEnded();
+ if (mVideoView.isPlaying()) {
+ mVideoView.stopPlayback();
+ }
mCurrentProxy = null;
- mVideoView.stopPlayback();
mLayout.removeView(mVideoView);
mVideoView = null;
if (mProgressView != null) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5cfbe73..4233af1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4882,6 +4882,9 @@
// we will not rewrite drag code here, but we
// will try fling if it applies.
WebViewCore.reducePriority();
+ // to get better performance, pause updating the
+ // picture
+ WebViewCore.pauseUpdatePicture(mWebViewCore);
// fall through to TOUCH_DRAG_MODE
} else {
break;
@@ -4916,8 +4919,14 @@
doFling();
break;
}
+ // fall through
+ case TOUCH_DRAG_START_MODE:
+ // TOUCH_DRAG_START_MODE should not happen for the real
+ // device as we almost certain will get a MOVE. But this
+ // is possible on emulator.
mLastVelocity = 0;
WebViewCore.resumePriority();
+ WebViewCore.resumeUpdatePicture(mWebViewCore);
break;
}
stopTouch();
@@ -4963,6 +4972,8 @@
private void startDrag() {
WebViewCore.reducePriority();
+ // to get better performance, pause updating the picture
+ WebViewCore.pauseUpdatePicture(mWebViewCore);
if (!mDragFromTextInput) {
nativeHideCursor();
}
@@ -5026,6 +5037,7 @@
}
if (mTouchMode == TOUCH_DRAG_MODE) {
WebViewCore.resumePriority();
+ WebViewCore.resumeUpdatePicture(mWebViewCore);
}
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
@@ -5360,6 +5372,7 @@
}
if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) {
WebViewCore.resumePriority();
+ WebViewCore.resumeUpdatePicture(mWebViewCore);
return;
}
float currentVelocity = mScroller.getCurrVelocity();
@@ -6153,7 +6166,7 @@
case UPDATE_ZOOM_RANGE: {
WebViewCore.RestoreState restoreState
= (WebViewCore.RestoreState) msg.obj;
- // mScrollX contains the new contentWidth
+ // mScrollX contains the new minPrefWidth
updateZoomRange(restoreState, getViewWidth(),
restoreState.mScrollX, false);
break;
@@ -6176,7 +6189,7 @@
boolean hasRestoreState = restoreState != null;
if (hasRestoreState) {
updateZoomRange(restoreState, viewSize.x,
- draw.mWidthHeight.x, true);
+ draw.mMinPrefWidth, true);
if (!mDrawHistory) {
mInZoomOverview = false;
@@ -6238,12 +6251,10 @@
// sMaxViewportWidth so that if the page doesn't behave
// well, the WebView won't go insane. limit the lower
// bound to match the default scale for mobile sites.
- // we choose the content width to be mZoomOverviewWidth.
- // this works for most of the sites. But some sites may
- // cause the page layout wider than it needs.
mZoomOverviewWidth = Math.min(sMaxViewportWidth, Math
- .max((int) (viewWidth / mDefaultScale),
- draw.mWidthHeight.x));
+ .max((int) (viewWidth / mDefaultScale), Math
+ .max(draw.mMinPrefWidth,
+ draw.mViewPoint.x)));
}
if (!mMinZoomScaleFixed) {
mMinZoomScale = (float) viewWidth / mZoomOverviewWidth;
@@ -6371,6 +6382,7 @@
break;
case RESUME_WEBCORE_PRIORITY:
WebViewCore.resumePriority();
+ WebViewCore.resumeUpdatePicture(mWebViewCore);
break;
case LONG_PRESS_CENTER:
@@ -6893,13 +6905,12 @@
new InvokeListBox(array, enabledArray, selectedArray));
}
- // viewWidth/contentWidth/updateZoomOverview are only used for mobile sites
private void updateZoomRange(WebViewCore.RestoreState restoreState,
- int viewWidth, int contentWidth, boolean updateZoomOverview) {
+ int viewWidth, int minPrefWidth, boolean updateZoomOverview) {
if (restoreState.mMinScale == 0) {
if (restoreState.mMobileSite) {
- if (contentWidth > Math.max(0, viewWidth)) {
- mMinZoomScale = (float) viewWidth / contentWidth;
+ if (minPrefWidth > Math.max(0, viewWidth)) {
+ mMinZoomScale = (float) viewWidth / minPrefWidth;
mMinZoomScaleFixed = false;
if (updateZoomOverview) {
WebSettings settings = getSettings();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 445e7ff..625e7ba 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1705,6 +1705,7 @@
Region mInvalRegion;
Point mViewPoint;
Point mWidthHeight;
+ int mMinPrefWidth;
RestoreState mRestoreState; // only non-null if it is for the first
// picture set after the first layout
boolean mFocusSizeChanged;
@@ -1724,6 +1725,13 @@
// layout.
draw.mFocusSizeChanged = nativeFocusBoundsChanged();
draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
+ if (mSettings.getUseWideViewPort()) {
+ draw.mMinPrefWidth = Math.max(
+ mViewportWidth == -1 ? WebView.DEFAULT_VIEWPORT_WIDTH
+ : (mViewportWidth == 0 ? mCurrentViewWidth
+ : mViewportWidth),
+ nativeGetContentMinPrefWidth());
+ }
if (mRestoreState != null) {
draw.mRestoreState = mRestoreState;
mRestoreState = null;
@@ -1752,9 +1760,9 @@
final DrawFilter mZoomFilter =
new PaintFlagsDrawFilter(ZOOM_BITS, Paint.LINEAR_TEXT_FLAG);
- final DrawFilter mScrollFilter = null;
- // If we need to trade more speed for less quality on slower devices
- // use this: new PaintFlagsDrawFilter(SCROLL_BITS, 0);
+ // If we need to trade better quality for speed, set mScrollFilter to null
+ final DrawFilter mScrollFilter =
+ new PaintFlagsDrawFilter(SCROLL_BITS, 0);
/* package */ void drawContentPicture(Canvas canvas, int color,
boolean animatingZoom,
@@ -2077,7 +2085,7 @@
restoreState.mDefaultScale = adjust;
// as mViewportWidth is not 0, it is not mobile site.
restoreState.mMobileSite = false;
- // for non-mobile site, we don't need contentWidth, set it as 0
+ // for non-mobile site, we don't need minPrefWidth, set it as 0
restoreState.mScrollX = 0;
Message.obtain(mWebView.mPrivateHandler,
WebView.UPDATE_ZOOM_RANGE, restoreState).sendToTarget();
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9e3e8a4..db71b21b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1031,7 +1031,8 @@
android:description="@string/permdesc_deletePackages"
android:protectionLevel="signatureOrSystem" />
- <!-- Allows an application to move location of installed package. -->
+ <!-- Allows an application to move location of installed package.
+ @hide -->
<permission android:name="android.permission.MOVE_PACKAGE"
android:label="@string/permlab_movePackage"
android:description="@string/permdesc_movePackage"
@@ -1207,7 +1208,8 @@
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signatureOrSystem" />
- <!-- Allow an application to read and write the cache partition. -->
+ <!-- Allow an application to read and write the cache partition.
+ @hide -->
<permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
android:label="@string/permlab_cache_filesystem"
android:description="@string/permdesc_cache_filesystem"
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
index 41ad27d..6b4f66d 100644
--- a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_throttle_warning.png b/core/res/res/drawable-hdpi/stat_sys_throttle_warning.png
new file mode 100644
index 0000000..c42b00c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_throttle_warning.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_throttled.png b/core/res/res/drawable-hdpi/stat_sys_throttled.png
new file mode 100644
index 0000000..e43fbae
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
index ee77526..d29c6c3 100644
--- a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_throttle_warning.png b/core/res/res/drawable-mdpi/stat_sys_throttle_warning.png
new file mode 100644
index 0000000..3688803
--- /dev/null
+++ b/core/res/res/drawable-mdpi/stat_sys_throttle_warning.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_throttled.png b/core/res/res/drawable-mdpi/stat_sys_throttled.png
new file mode 100644
index 0000000..efb64ad
--- /dev/null
+++ b/core/res/res/drawable-mdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index a4b2357..945d283 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -152,5 +152,19 @@
android:layout_marginBottom="80dip"
/>
+ <!-- emergency call button shown when sim is PUKd and tab_selector is
+ hidden -->
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableLeft="@drawable/ic_emergency"
+ android:layout_centerInParent="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="80dip"
+ style="@style/Widget.Button.Transparent"
+ android:drawablePadding="8dip"
+ />
+
</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index e1c9772..6b76004e 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -153,4 +153,16 @@
android:layout_marginRight="80dip"
/>
+ <!-- emergency call button shown when sim is PUKd and tab_selector is
+ hidden -->
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableLeft="@drawable/ic_emergency"
+ style="@style/Widget.Button.Transparent"
+ android:drawablePadding="8dip"
+ android:layout_marginRight="80dip"
+ />
+
</LinearLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 29a815f..7ebbab0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -128,11 +128,15 @@
in to AC and 2 to stay on when plugged in to USB. (So 3 for both.) -->
<integer name="config_carDockKeepsScreenOn">1</integer>
- <!-- Control whether being in the desk dock should enable accelerometer based screen orientation -->
+ <!-- Control whether being in the desk dock should enable accelerometer
+ based screen orientation. Note this should probably default to true
+ like car dock, but we haven't had a chance to test it. -->
<bool name="config_deskDockEnablesAccelerometer">false</bool>
- <!-- Control whether being in the car dock should enable accelerometer based screen orientation -->
- <bool name="config_carDockEnablesAccelerometer">false</bool>
+ <!-- Control whether being in the car dock should enable accelerometer based
+ screen orientation. This defaults to true because putting a device in
+ a car dock make the accelerometer more a physical input (like a lid). -->
+ <bool name="config_carDockEnablesAccelerometer">true</bool>
<!-- Indicate whether the lid state impacts the accessibility of
the physical keyboard. 0 means it doesn't, 1 means it is accessible
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 48d1ad7..36dc07c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2257,4 +2257,14 @@
<!-- Shown when the device is tethered -->
<string name="tethered_notification_title">Tethering active</string>
<string name="tethered_notification_message">Touch to configure</string>
+
+ <!-- Strings for throttling notification -->
+ <!-- Shown when the user is in danger of being throttled -->
+ <string name="throttle_warning_notification_title">Excessive data use warning</string>
+ <string name="throttle_warning_notification_message">If your data use pattern continues you may be subject to bandwidth restrictions - touch for more information</string>
+
+ <!-- Strings for throttling notification -->
+ <!-- Shown when the users bandwidth is reduced because of excessive data use -->
+ <string name="throttled_notification_title">Bandwidth Restricted</string>
+ <string name="throttled_notification_message">Your mobile data bandwidth is being reduced because of excessive data use - touch for more information</string>
</resources>
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 152f02e..7fa64ca 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -328,14 +328,14 @@
boolean checkSd = false;
int setLoc = 0;
try {
- setLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION);
+ setLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.SET_INSTALL_LOCATION);
} catch (SettingNotFoundException e) {
failStr(e);
}
if (setLoc == 1) {
int userPref = APP_INSTALL_AUTO;
try {
- userPref = Settings.System.getInt(mContext.getContentResolver(), Settings.System.DEFAULT_INSTALL_LOCATION);
+ userPref = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.DEFAULT_INSTALL_LOCATION);
} catch (SettingNotFoundException e) {
failStr(e);
}
@@ -1302,8 +1302,8 @@
boolean userSetting = false;
int origDefaultLoc = PackageInfo.INSTALL_LOCATION_AUTO;
try {
- userSetting = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION) != 0;
- origDefaultLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.System.DEFAULT_INSTALL_LOCATION);
+ userSetting = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.SET_INSTALL_LOCATION) != 0;
+ origDefaultLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.DEFAULT_INSTALL_LOCATION);
} catch (SettingNotFoundException e1) {
}
return origDefaultLoc;
@@ -1311,7 +1311,7 @@
private void setInstallLoc(int loc) {
Settings.System.putInt(mContext.getContentResolver(),
- Settings.System.DEFAULT_INSTALL_LOCATION, loc);
+ Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
}
/*
* Tests for moving apps between internal and external storage
@@ -1963,7 +1963,7 @@
*/
private boolean getUserSettingSetInstallLocation() {
try {
- return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION) != 0;
+ return Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.SET_INSTALL_LOCATION) != 0;
} catch (SettingNotFoundException e1) {
}
@@ -1972,7 +1972,7 @@
private void setUserSettingSetInstallLocation(boolean value) {
Settings.System.putInt(mContext.getContentResolver(),
- Settings.System.SET_INSTALL_LOCATION, value ? 1 : 0);
+ Settings.Secure.SET_INSTALL_LOCATION, value ? 1 : 0);
}
private void setUserX(boolean enable, int userSetting, int iloc) {
boolean origUserSetting = getUserSettingSetInstallLocation();
diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd
index 1255949..734a79d 100644
--- a/docs/html/guide/topics/manifest/manifest-element.jd
+++ b/docs/html/guide/topics/manifest/manifest-element.jd
@@ -109,7 +109,7 @@
</dd>
<dt><a name="install"></a>{@code android:installLocation}</dt>
-<dd>The default install location for your application.
+<dd>The default install location for the application.
<p>This attribute was introduced in API Level 8.</p>
<p>The following keyword strings are accepted:</p>
@@ -124,15 +124,15 @@
saved preference.</td>
</tr><tr>
<td>"{@code internalOnly}"</td>
- <td>Request to be installed only on the internal device storage. If this is set, then
-the application will never be installed on the external storage (SD card). If the internal storage
-is full, then the application will not install.</td>
+ <td>The application requests to be installed on the internal device storage only. If this is set,
+then the application will never be installed on the external storage (SD card). If the internal
+storage is full, then the system will not install the application.</td>
</tr><tr>
<td>"{@code preferExternal}"</td>
- <td>Prefer to be installed on external storage (SD card). There is no guarantee that the system
-will honor this request. The application might be installed on internal storage if the
-external media is unavailable or full, or if the application uses the forward-locking mechanism
-(not supported on external storage).</td>
+ <td>The application prefers to be installed on the external storage (SD card). There is no
+guarantee that the system will honor this request. The application might be installed on internal
+storage if the external media is unavailable or full, or if the application uses the forward-locking
+mechanism (not supported on external storage).</td>
</tr>
</table>
@@ -149,7 +149,8 @@
</ul>
<p>The user may also request to move an application from the internal storage to the external
-storage. However, this will not be allowed if this attribute is set to {@code internalOnly}.
+storage. However, the system will not allow the user to move the application to external storage if
+this attribute is set to {@code internalOnly}.
</p>
</dd>
@@ -159,9 +160,7 @@
<!-- ##api level indication## -->
<dt>introduced in:</dt>
-<dd>API Level 1 for all attributes except for
-<code><a href="#uidlabel">sharedUserLabel</a></code>, which was added in
-level 3.</dd>
+<dd>API Level 1 for all attributes, unless noted otherwise in the attribute description.</dd>
<p>
<dt>see also:</dt>
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index b5d1e7a..ea31942 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -54,7 +54,7 @@
private:
enum {
- kBufferSize = 32 * 1024,
+ kBufferSize = 64 * 1024,
// If we encounter a socket-read error we'll try reconnecting
// and restarting the read for at most this many times.
@@ -77,9 +77,6 @@
int mStartingPort;
HTTPStream *mHttp;
- char *mHost;
- int mPort;
- char *mPath;
void *mBuffer;
size_t mBufferLength;
@@ -95,6 +92,8 @@
ssize_t sendRangeRequest(size_t offset);
void initHeaders(const KeyedVector<String8, String8> *overrides);
+ status_t connectWithRedirectsAndRange(off_t rangeStart);
+
HTTPDataSource(const HTTPDataSource &);
HTTPDataSource &operator=(const HTTPDataSource &);
};
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e7022f4..63dfa67 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1091,7 +1091,7 @@
}
dataSource = new CachingDataSource(
- mConnectingDataSource, 32 * 1024, 20);
+ mConnectingDataSource, 64 * 1024, 10);
mConnectingDataSource.clear();
} else {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 284e3bc..86e4bfe 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -105,7 +105,7 @@
if (httpSource->connect() != OK) {
return NULL;
}
- source = new CachingDataSource(httpSource, 32 * 1024, 20);
+ source = new CachingDataSource(httpSource, 64 * 1024, 10);
} else {
// Assume it's a filename.
source = new FileSource(uri);
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index 61ffa8d..a0b1993 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -29,71 +29,101 @@
namespace android {
-// Given a connected HTTPStream, determine if the given path redirects
-// somewhere else, if so, disconnect the stream, update host path and port
-// accordingly and return true, otherwise return false and leave the stream
-// connected.
-static bool PerformRedirectIfNecessary(
- HTTPStream *http, const String8 &headers,
- string *host, string *path, int *port) {
- String8 request;
- request.append("GET ");
- request.append(path->c_str());
- request.append(" HTTP/1.1\r\n");
- request.append(headers);
- request.append("Host: ");
- request.append(host->c_str());
- request.append("\r\n\r\n");
+status_t HTTPDataSource::connectWithRedirectsAndRange(off_t rangeStart) {
+ string host = mStartingHost.string();
+ string path = mStartingPath.string();
+ int port = mStartingPort;
- status_t err = http->send(request.string());
+ LOGV("Connecting to host '%s', port %d, path '%s'",
+ host.c_str(), port, path.c_str());
- int http_status;
- if (err == OK) {
- err = http->receive_header(&http_status);
+ int numRedirectsRemaining = 5;
+ while (numRedirectsRemaining-- > 0) {
+ status_t err = mHttp->connect(host.c_str(), port);
+
+ if (err != OK) {
+ return err;
+ }
+
+ String8 request;
+ request.append("GET ");
+ request.append(path.c_str());
+ request.append(" HTTP/1.1\r\n");
+ request.append(mHeaders);
+ request.append("Host: ");
+ request.append(host.c_str());
+ request.append("\r\n");
+
+ if (rangeStart > 0) {
+ char range[128];
+ sprintf(range, "Range: bytes=%ld-\r\n", rangeStart);
+
+ request.append(range);
+ }
+
+ request.append("\r\n");
+
+ err = mHttp->send(request.string());
+
+ if (err != OK) {
+ return err;
+ }
+
+ int httpStatus;
+ err = mHttp->receive_header(&httpStatus);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (httpStatus >= 200 && httpStatus < 300) {
+ return OK;
+ }
+
+ if (httpStatus != 301 && httpStatus != 302) {
+ LOGE("HTTP request failed w/ http status %d", httpStatus);
+ return ERROR_IO;
+ }
+
+ string location;
+ CHECK(mHttp->find_header_value("Location", &location));
+
+ CHECK(string(location, 0, 7) == "http://");
+ location.erase(0, 7);
+ string::size_type slashPos = location.find('/');
+ if (slashPos == string::npos) {
+ slashPos = location.size();
+ location += '/';
+ }
+
+ mHttp->disconnect();
+
+ LOGV("Redirecting to %s\n", location.c_str());
+
+ host = string(location, 0, slashPos);
+
+ string::size_type colonPos = host.find(':');
+ if (colonPos != string::npos) {
+ const char *start = host.c_str() + colonPos + 1;
+ char *end;
+ long tmp = strtol(start, &end, 10);
+ CHECK(end > start && (*end == '\0'));
+
+ port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80;
+
+ host.erase(colonPos, host.size() - colonPos);
+ } else {
+ port = 80;
+ }
+
+ path = string(location, slashPos);
+
+ mStartingHost = host.c_str();
+ mStartingPath = path.c_str();
+ mStartingPort = port;
}
- if (err != OK) {
- return false;
- }
-
- if (http_status != 301 && http_status != 302) {
- return false;
- }
-
- string location;
- CHECK(http->find_header_value("Location", &location));
-
- CHECK(string(location, 0, 7) == "http://");
- location.erase(0, 7);
- string::size_type slashPos = location.find('/');
- if (slashPos == string::npos) {
- slashPos = location.size();
- location += '/';
- }
-
- http->disconnect();
-
- LOGI("Redirecting to %s\n", location.c_str());
-
- *host = string(location, 0, slashPos);
-
- string::size_type colonPos = host->find(':');
- if (colonPos != string::npos) {
- const char *start = host->c_str() + colonPos + 1;
- char *end;
- long tmp = strtol(start, &end, 10);
- CHECK(end > start && (*end == '\0'));
-
- *port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80;
-
- host->erase(colonPos, host->size() - colonPos);
- } else {
- *port = 80;
- }
-
- *path = string(location, slashPos);
-
- return true;
+ return ERROR_IO;
}
HTTPDataSource::HTTPDataSource(
@@ -147,10 +177,6 @@
mState = DISCONNECTED;
mHttp = new HTTPStream;
- mHost = NULL;
- mPort = 0;
- mPath = NULL;
-
initHeaders(headers);
mBuffer = malloc(kBufferSize);
@@ -173,29 +199,18 @@
mBufferOffset = 0;
mContentLengthValid = false;
- string host = mStartingHost.string();
- string path = mStartingPath.string();
- int port = mStartingPort;
+ status_t err = connectWithRedirectsAndRange(0);
- LOGI("Connecting to host '%s', port %d, path '%s'",
- host.c_str(), port, path.c_str());
+ if (err != OK) {
+ Mutex::Autolock autoLock(mStateLock);
- int numRedirectsRemaining = 5;
- do {
- status_t err = mHttp->connect(host.c_str(), port);
-
- if (err != OK) {
- Mutex::Autolock autoLock(mStateLock);
-
- if (mState != CONNECTING) {
- LOGV("connect() cancelled");
- }
- mState = DISCONNECTED;
-
- return err;
+ if (mState != CONNECTING) {
+ LOGV("connect() cancelled");
}
- } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port)
- && numRedirectsRemaining-- > 0);
+ mState = DISCONNECTED;
+
+ return err;
+ }
string value;
if (mHttp->find_header_value("Content-Length", &value)) {
@@ -204,10 +219,6 @@
mContentLengthValid = true;
}
- mHost = strdup(host.c_str());
- mPort = port;
- mPath = strdup(path.c_str());
-
Mutex::Autolock autoLock(mStateLock);
if (mState != CONNECTING) {
@@ -219,6 +230,7 @@
}
mState = CONNECTED;
+
return OK;
}
@@ -264,56 +276,13 @@
free(mBuffer);
mBuffer = NULL;
-
- if (mPath) {
- free(mPath);
- mPath = NULL;
- }
-
- if (mHost) {
- free(mHost);
- mHost = NULL;
- }
}
ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
- char host[128];
- sprintf(host, "Host: %s\r\n", mHost);
+ status_t err = connectWithRedirectsAndRange(offset);
- char range[128];
- if (offset > 0) {
- sprintf(range, "Range: bytes=%d-\r\n\r\n", offset);
- } else {
- range[0] = '\0';
- }
-
- int http_status;
-
- status_t err;
- int attempt = 1;
- for (;;) {
- if ((err = mHttp->send("GET ")) != OK
- || (err = mHttp->send(mPath)) != OK
- || (err = mHttp->send(" HTTP/1.1\r\n")) != OK
- || (err = mHttp->send(mHeaders.string())) != OK
- || (err = mHttp->send(host)) != OK
- || (err = mHttp->send(range)) != OK
- || (err = mHttp->send("\r\n")) != OK
- || (err = mHttp->receive_header(&http_status)) != OK) {
-
- if (attempt == 3) {
- return err;
- }
-
- mHttp->connect(mHost, mPort);
- ++attempt;
- } else {
- break;
- }
- }
-
- if ((http_status / 100) != 2) {
- return UNKNOWN_ERROR;
+ if (err != OK) {
+ return err;
}
string value;
@@ -349,6 +318,10 @@
memcpy(data, (const char *)mBuffer + (offset - mBufferOffset), copy);
+ if (copy < size) {
+ LOGV("short read (1), returning %d vs. %d requested", copy, size);
+ }
+
return copy;
}
@@ -388,8 +361,10 @@
if (num_bytes_received < 0
|| (mContentLengthValid && num_bytes_received < contentLength)) {
if (mNumRetriesLeft-- > 0) {
- disconnect();
- if (connect() == OK) {
+ mHttp->disconnect();
+ mBufferLength = 0;
+ num_bytes_received = connectWithRedirectsAndRange(mBufferOffset);
+ if (num_bytes_received == OK) {
LOGI("retrying connection succeeded.");
goto rinse_repeat;
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 14c8806..57f9ce7 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -339,25 +339,19 @@
checkBoth = true;
break check_inner;
}
- // Check if user option is enabled
- boolean setInstallLoc = Settings.System.getInt(getApplicationContext()
+ // Pick user preference
+ int installPreference = Settings.System.getInt(getApplicationContext()
.getContentResolver(),
- Settings.System.SET_INSTALL_LOCATION, 0) != 0;
- if (setInstallLoc) {
- // Pick user preference
- int installPreference = Settings.System.getInt(getApplicationContext()
- .getContentResolver(),
- Settings.System.DEFAULT_INSTALL_LOCATION,
- PackageHelper.APP_INSTALL_AUTO);
- if (installPreference == PackageHelper.APP_INSTALL_INTERNAL) {
- checkInt = true;
- checkBoth = true;
- break check_inner;
- } else if (installPreference == PackageHelper.APP_INSTALL_EXTERNAL) {
- checkExt = true;
- checkBoth = true;
- break check_inner;
- }
+ Settings.Secure.DEFAULT_INSTALL_LOCATION,
+ PackageHelper.APP_INSTALL_AUTO);
+ if (installPreference == PackageHelper.APP_INSTALL_INTERNAL) {
+ checkInt = true;
+ checkBoth = true;
+ break check_inner;
+ } else if (installPreference == PackageHelper.APP_INSTALL_EXTERNAL) {
+ checkExt = true;
+ checkBoth = true;
+ break check_inner;
}
// Fall back to default policy if nothing else is specified.
checkInt = true;
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 34302c4..185d72a9 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -56,10 +56,6 @@
<bool name="def_mount_ums_autostart">false</bool>
<bool name="def_mount_ums_prompt">true</bool>
<bool name="def_mount_ums_notify_enabled">true</bool>
- <!-- Enable User preference for setting install location -->
- <bool name="set_install_location">true</bool>
- <!-- Default install location if user preference for setting install location is turned on. -->
- <integer name="def_install_location">2</integer>
<!-- user interface sound effects -->
<integer name="def_power_sounds_enabled">1</integer>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index d0e9dd9..0c0bf93 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -39,6 +39,8 @@
import android.util.Config;
import android.util.Log;
import android.util.Xml;
+
+import com.android.internal.content.PackageHelper;
import com.android.internal.telephony.RILConstants;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
@@ -61,7 +63,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 55;
+ private static final int DATABASE_VERSION = 56;
private Context mContext;
@@ -608,21 +610,8 @@
if (upgradeVersion == 50) {
/*
- * New settings for set install location UI.
+ * Install location no longer initiated here.
*/
- db.beginTransaction();
- SQLiteStatement stmt = null;
- try {
- stmt = db.compileStatement("INSERT INTO system(name,value)"
- + " VALUES(?,?);");
- loadBooleanSetting(stmt, Settings.System.SET_INSTALL_LOCATION,
- R.bool.set_install_location);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- if (stmt != null) stmt.close();
- }
-
upgradeVersion = 51;
}
@@ -663,21 +652,8 @@
if (upgradeVersion == 53) {
/*
- * New settings for set install location UI.
+ * New settings for set install location UI no longer initiated here.
*/
- db.beginTransaction();
- SQLiteStatement stmt = null;
- try {
- stmt = db.compileStatement("INSERT INTO system(name,value)"
- + " VALUES(?,?);");
- loadIntegerSetting(stmt, Settings.System.DEFAULT_INSTALL_LOCATION,
- R.integer.def_install_location);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- if (stmt != null) stmt.close();
- }
-
upgradeVersion = 54;
}
@@ -696,6 +672,28 @@
upgradeVersion = 55;
}
+ if (upgradeVersion == 55) {
+ /* Move the install location settings. */
+ String[] settingsToMove = {
+ Secure.SET_INSTALL_LOCATION,
+ Secure.DEFAULT_INSTALL_LOCATION
+ };
+ moveFromSystemToSecure(db, settingsToMove);
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT INTO system(name,value)"
+ + " VALUES(?,?);");
+ loadSetting(stmt, Secure.SET_INSTALL_LOCATION, 0);
+ loadSetting(stmt, Secure.DEFAULT_INSTALL_LOCATION,
+ PackageHelper.APP_INSTALL_AUTO);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 56;
+ }
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -1021,10 +1019,9 @@
loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
R.bool.def_notification_pulse);
- loadBooleanSetting(stmt, Settings.System.SET_INSTALL_LOCATION,
- R.bool.set_install_location);
- loadIntegerSetting(stmt, Settings.System.DEFAULT_INSTALL_LOCATION,
- R.integer.def_install_location);
+ loadSetting(stmt, Settings.Secure.SET_INSTALL_LOCATION, 0);
+ loadSetting(stmt, Settings.Secure.DEFAULT_INSTALL_LOCATION,
+ PackageHelper.APP_INSTALL_AUTO);
loadUISoundEffectsSettings(stmt);
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 95dbf3c..e6663d4 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -31,8 +31,9 @@
import android.app.IActivityManager;
import android.app.admin.IDevicePolicyManager;
import android.app.backup.IBackupManager;
-import android.content.ComponentName;
import android.content.Context;
+import android.content.ComponentName;
+import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
@@ -83,6 +84,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.security.SystemKeyStore;
import android.util.*;
import android.view.Display;
@@ -582,11 +584,11 @@
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
res.pkg.applicationInfo.packageName,
- extras);
+ extras, null);
if (update) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
res.pkg.applicationInfo.packageName,
- extras);
+ extras, null);
}
if (res.removedInfo.args != null) {
// Remove the replaced package's older resources safely now
@@ -4471,7 +4473,8 @@
}
};
- private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
+ private static final void sendPackageBroadcast(String action, String pkg,
+ Bundle extras, IIntentReceiver finishedReceiver) {
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
@@ -4481,9 +4484,8 @@
intent.putExtras(extras);
}
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- am.broadcastIntent(
- null, intent,
- null, null, 0, null, null, null, false, false);
+ am.broadcastIntent(null, intent, null, finishedReceiver,
+ 0, null, null, null, finishedReceiver != null, false);
} catch (RemoteException ex) {
}
}
@@ -4605,12 +4607,14 @@
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, removedUid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
+ extras, null);
}
if (addedPackage != null) {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, addedUid);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
+ extras, null);
}
}
@@ -6052,8 +6056,8 @@
extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, null);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, null);
}
}
// Force a gc here.
@@ -6084,10 +6088,10 @@
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
if (removedPackage != null) {
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras, null);
}
if (removedUid >= 0) {
- sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
+ sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null);
}
}
}
@@ -6789,7 +6793,7 @@
extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
extras.putInt(Intent.EXTRA_UID, packageUid);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null);
}
public String getInstallerPackageName(String packageName) {
@@ -9512,7 +9516,7 @@
}
private void sendResourcesChangedBroadcast(boolean mediaStatus,
- ArrayList<String> pkgList, int uidArr[]) {
+ ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
int size = pkgList.size();
if (size > 0) {
// Send broadcasts here
@@ -9524,7 +9528,7 @@
}
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
- sendPackageBroadcast(action, null, extras);
+ sendPackageBroadcast(action, null, extras, finishedReceiver);
}
}
@@ -9611,7 +9615,7 @@
}
// Send a broadcast to let everyone know we are done processing
if (pkgList.size() > 0) {
- sendResourcesChangedBroadcast(true, pkgList, uidArr);
+ sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
}
if (doGc) {
Runtime.getRuntime().gc();
@@ -9649,10 +9653,15 @@
}
// Send broadcasts
if (pkgList.size() > 0) {
- sendResourcesChangedBroadcast(false, pkgList, uidArr);
+ sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
+ public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
+ boolean ordered, boolean sticky) throws RemoteException {
+ // Force gc now that everyone is done cleaning up, to release
+ // references on assets.
+ Runtime.getRuntime().gc();
+ }
+ });
}
- // Force gc
- Runtime.getRuntime().gc();
// Just unmount all valid containers.
for (SdInstallArgs args : keys) {
synchronized (mInstallLock) {
@@ -9742,7 +9751,7 @@
}
if (returnCode == PackageManager.MOVE_SUCCEEDED) {
// Send resources unavailable broadcast
- sendResourcesChangedBroadcast(false, pkgList, uidArr);
+ sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
// Update package code and resource paths
synchronized (mInstallLock) {
synchronized (mPackages) {
@@ -9793,7 +9802,7 @@
}
}
// Send resources available broadcast
- sendResourcesChangedBroadcast(true, pkgList, uidArr);
+ sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
}
}
}
@@ -9821,5 +9830,26 @@
}
});
}
+
+ public boolean setInstallLocation(int loc) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
+ if (getInstallLocation() == loc) {
+ return true;
+ }
+ if (loc == PackageHelper.APP_INSTALL_AUTO ||
+ loc == PackageHelper.APP_INSTALL_INTERNAL ||
+ loc == PackageHelper.APP_INSTALL_EXTERNAL) {
+ android.provider.Settings.System.putInt(mContext.getContentResolver(),
+ android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
+ return true;
+ }
+ return false;
+ }
+
+ public int getInstallLocation() {
+ return android.provider.Settings.System.getInt(mContext.getContentResolver(),
+ android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, PackageHelper.APP_INSTALL_AUTO);
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 25a60a6..9d5d035 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -99,6 +99,7 @@
DockObserver dock = null;
UiModeManagerService uiMode = null;
RecognitionManagerService recognition = null;
+ ThrottleService throttle = null;
// Critical services...
try {
@@ -269,6 +270,15 @@
}
try {
+ Slog.i(TAG, "Throttle Service");
+ throttle = new ThrottleService(context);
+ ServiceManager.addService(
+ Context.THROTTLE_SERVICE, throttle);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting ThrottleService", e);
+ }
+
+ try {
Slog.i(TAG, "Accessibility Manager");
ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
new AccessibilityManagerService(context));
@@ -457,6 +467,7 @@
final BatteryService batteryF = battery;
final ConnectivityService connectivityF = connectivity;
final DockObserver dockF = dock;
+ final ThrottleService throttleF = throttle;
final UiModeManagerService uiModeF = uiMode;
final AppWidgetService appWidgetF = appWidget;
final WallpaperManagerService wallpaperF = wallpaper;
@@ -488,6 +499,7 @@
if (wallpaperF != null) wallpaperF.systemReady();
if (immF != null) immF.systemReady();
if (locationF != null) locationF.systemReady();
+ if (throttleF != null) throttleF.systemReady();
}
});
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
new file mode 100644
index 0000000..36931b2
--- /dev/null
+++ b/services/java/com/android/server/ThrottleService.java
@@ -0,0 +1,729 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.SharedPreferences;
+import android.net.IThrottleManager;
+import android.net.ThrottleManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Random;
+
+// TODO - add comments - reference the ThrottleManager for public API
+public class ThrottleService extends IThrottleManager.Stub {
+
+ private static final String TESTING_ENABLED_PROPERTY = "persist.throttle.testing";
+
+ private static final String TAG = "ThrottleService";
+ private static boolean DBG = true;
+ private Handler mHandler;
+ private HandlerThread mThread;
+
+ private Context mContext;
+
+ private int mPolicyPollPeriodSec;
+ private static final int DEFAULT_POLLING_PERIOD_SEC = 60 * 10;
+ private static final int TESTING_POLLING_PERIOD_SEC = 60 * 1;
+
+ private static final int TESTING_RESET_PERIOD_SEC = 60 * 3;
+
+ private static final int PERIOD_COUNT = 6;
+
+ private long mPolicyThreshold;
+ // TODO - remove testing stuff?
+ private static final long DEFAULT_TESTING_THRESHOLD = 1 * 1024 * 1024;
+ private static final long DEFAULT_THRESHOLD = 0; // off by default
+
+ private int mPolicyThrottleValue;
+ private static final int DEFAULT_THROTTLE_VALUE = 100; // 100 Kbps
+
+ private int mPolicyResetDay; // 1-28
+
+ private long mLastRead; // read byte count from last poll
+ private long mLastWrite; // write byte count from last poll
+
+ private static final String ACTION_POLL = "com.android.server.ThrottleManager.action.POLL";
+ private static int POLL_REQUEST = 0;
+ private PendingIntent mPendingPollIntent;
+ private static final String ACTION_RESET = "com.android.server.ThorottleManager.action.RESET";
+ private static int RESET_REQUEST = 1;
+ private PendingIntent mPendingResetIntent;
+
+ private INetworkManagementService mNMService;
+ private AlarmManager mAlarmManager;
+ private NotificationManager mNotificationManager;
+
+ private DataRecorder mRecorder;
+
+ private int mThrottleLevel; // 0 for none, 1 for first throttle val, 2 for next, etc
+
+ private String mPolicyIface;
+
+ private static final int NOTIFICATION_WARNING = 2;
+ private static final int NOTIFICATION_ALL = 0xFFFFFFFF;
+ private int mPolicyNotificationsAllowedMask;
+
+ private Notification mThrottlingNotification;
+ private boolean mWarningNotificationSent = false;
+
+ public ThrottleService(Context context) {
+ if (DBG) Slog.d(TAG, "Starting ThrottleService");
+ mContext = context;
+
+ mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+ Intent pollIntent = new Intent(ACTION_POLL, null);
+ mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
+ Intent resetIntent = new Intent(ACTION_RESET, null);
+ mPendingResetIntent = PendingIntent.getBroadcast(mContext, RESET_REQUEST, resetIntent, 0);
+
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ mNMService = INetworkManagementService.Stub.asInterface(b);
+
+ mNotificationManager = (NotificationManager)mContext.getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ }
+
+ private void enforceAccessPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NETWORK_STATE,
+ "ThrottleService");
+ }
+
+ public synchronized long getResetTime(String iface) {
+ enforceAccessPermission();
+ if (iface.equals(mPolicyIface) && (mRecorder != null)) mRecorder.getPeriodEnd();
+ return 0;
+ }
+ public synchronized long getPeriodStartTime(String iface) {
+ enforceAccessPermission();
+ if (iface.equals(mPolicyIface) && (mRecorder != null)) mRecorder.getPeriodStart();
+ return 0;
+ }
+ //TODO - a better name? getCliffByteCountThreshold?
+ public synchronized long getCliffThreshold(String iface, int cliff) {
+ enforceAccessPermission();
+ if ((cliff == 0) && iface.equals(mPolicyIface)) {
+ return mPolicyThreshold;
+ }
+ return 0;
+ }
+ // TODO - a better name? getThrottleRate?
+ public synchronized int getCliffLevel(String iface, int cliff) {
+ enforceAccessPermission();
+ if ((cliff == 0) && iface.equals(mPolicyIface)) {
+ return mPolicyThrottleValue;
+ }
+ return 0;
+ }
+
+ public synchronized long getByteCount(String iface, int dir, int period, int ago) {
+ enforceAccessPermission();
+ if (iface.equals(mPolicyIface) &&
+ (period == ThrottleManager.PERIOD_CYCLE) &&
+ (mRecorder != null)) {
+ if (dir == ThrottleManager.DIRECTION_TX) return mRecorder.getPeriodTx(ago);
+ if (dir == ThrottleManager.DIRECTION_RX) return mRecorder.getPeriodRx(ago);
+ }
+ return 0;
+ }
+
+ // TODO - a better name - getCurrentThrottleRate?
+ public synchronized int getThrottle(String iface) {
+ enforceAccessPermission();
+ if (iface.equals(mPolicyIface) && (mThrottleLevel == 1)) {
+ return mPolicyThrottleValue;
+ }
+ return 0;
+ }
+
+ void systemReady() {
+ if (DBG) Slog.d(TAG, "systemReady");
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget();
+ }
+ }, new IntentFilter(ACTION_POLL));
+
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
+ }
+ }, new IntentFilter(ACTION_RESET));
+
+ // use a new thread as we don't want to stall the system for file writes
+ mThread = new HandlerThread(TAG);
+ mThread.start();
+ mHandler = new MyHandler(mThread.getLooper());
+ mHandler.obtainMessage(EVENT_REBOOT_RECOVERY).sendToTarget();
+ }
+
+
+ private static final int EVENT_REBOOT_RECOVERY = 0;
+ private static final int EVENT_POLICY_CHANGED = 1;
+ private static final int EVENT_POLL_ALARM = 2;
+ private static final int EVENT_RESET_ALARM = 3;
+ private class MyHandler extends Handler {
+ public MyHandler(Looper l) {
+ super(l);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_REBOOT_RECOVERY:
+ onRebootRecovery();
+ break;
+ case EVENT_POLICY_CHANGED:
+ onPolicyChanged();
+ break;
+ case EVENT_POLL_ALARM:
+ onPollAlarm();
+ break;
+ case EVENT_RESET_ALARM:
+ onResetAlarm();
+ }
+ }
+
+ private void onRebootRecovery() {
+ if (DBG) Slog.d(TAG, "onRebootRecovery");
+ // check for sim change TODO
+ // reregister for notification of policy change
+
+ // register for roaming indication change
+ // check for roaming TODO
+
+ mRecorder = new DataRecorder(mContext, ThrottleService.this);
+
+ // get policy
+ mHandler.obtainMessage(EVENT_POLICY_CHANGED).sendToTarget();
+
+ // evaluate current conditions
+ mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget();
+ }
+
+ private void onSimChange() {
+ // TODO
+ }
+
+ // check for new policy info (threshold limit/value/etc)
+ private void onPolicyChanged() {
+ boolean testing = SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true");
+
+ int pollingPeriod = DEFAULT_POLLING_PERIOD_SEC;
+ if (testing) pollingPeriod = TESTING_POLLING_PERIOD_SEC;
+ mPolicyPollPeriodSec = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.THROTTLE_POLLING_SEC, pollingPeriod);
+
+ // TODO - remove testing stuff?
+ long defaultThreshold = DEFAULT_THRESHOLD;
+ if (testing) defaultThreshold = DEFAULT_TESTING_THRESHOLD;
+ synchronized (ThrottleService.this) {
+ mPolicyThreshold = Settings.Secure.getLong(mContext.getContentResolver(),
+ Settings.Secure.THROTTLE_THRESHOLD, defaultThreshold);
+ mPolicyThrottleValue = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.THROTTLE_VALUE, DEFAULT_THROTTLE_VALUE);
+ }
+ mPolicyResetDay = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.THROTTLE_RESET_DAY, -1);
+ if (mPolicyResetDay == -1 ||
+ ((mPolicyResetDay < 1) || (mPolicyResetDay > 28))) {
+ Random g = new Random();
+ mPolicyResetDay = 1 + g.nextInt(28); // 1-28
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.THROTTLE_RESET_DAY, mPolicyResetDay);
+ }
+ synchronized (ThrottleService.this) {
+ mPolicyIface = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.THROTTLE_IFACE);
+ // TODO - read default from resource so it's device-specific
+ if (mPolicyIface == null) mPolicyIface = "rmnet0";
+ }
+
+ mPolicyNotificationsAllowedMask = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.THROTTLE_NOTIFICATION_TYPE, NOTIFICATION_ALL);
+
+ Slog.d(TAG, "onPolicyChanged testing=" + testing +", period=" + mPolicyPollPeriodSec +
+ ", threshold=" + mPolicyThreshold + ", value=" + mPolicyThrottleValue +
+ ", resetDay=" + mPolicyResetDay + ", noteType=" +
+ mPolicyNotificationsAllowedMask);
+
+ Calendar end = calculatePeriodEnd();
+ Calendar start = calculatePeriodStart(end);
+
+ mRecorder.setNextPeriod(start,end);
+
+ mAlarmManager.cancel(mPendingResetIntent);
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP, end.getTimeInMillis(),
+ mPendingResetIntent);
+ }
+
+ private void onPollAlarm() {
+ long now = SystemClock.elapsedRealtime();
+ long next = now + mPolicyPollPeriodSec*1000;
+ long incRead = 0;
+ long incWrite = 0;
+ try {
+ incRead = mNMService.getInterfaceRxCounter(mPolicyIface) - mLastRead;
+ incWrite = mNMService.getInterfaceTxCounter(mPolicyIface) - mLastWrite;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "got remoteException in onPollAlarm:" + e);
+ }
+
+ mRecorder.addData(incRead, incWrite);
+
+ long periodRx = mRecorder.getPeriodRx(0);
+ long periodTx = mRecorder.getPeriodTx(0);
+ long total = periodRx + periodTx;
+ if (DBG) {
+ Slog.d(TAG, "onPollAlarm - now =" + now + ", read =" + incRead +
+ ", written =" + incWrite + ", new total =" + total);
+ }
+ mLastRead += incRead;
+ mLastWrite += incWrite;
+
+ checkThrottleAndPostNotification(total);
+
+ Intent broadcast = new Intent(ThrottleManager.THROTTLE_POLL_ACTION);
+ broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_READ, periodRx);
+ broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_WRITE, periodTx);
+ broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, mRecorder.getPeriodStart());
+ broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, mRecorder.getPeriodEnd());
+ mContext.sendStickyBroadcast(broadcast);
+
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, next, mPendingPollIntent);
+ }
+
+ private void checkThrottleAndPostNotification(long currentTotal) {
+ // are we even doing this?
+ if (mPolicyThreshold == 0)
+ return;
+
+ // check if we need to throttle
+ if (currentTotal > mPolicyThreshold) {
+ if (mThrottleLevel != 1) {
+ synchronized (ThrottleService.this) {
+ mThrottleLevel = 1;
+ }
+ if (DBG) Slog.d(TAG, "Threshold " + mPolicyThreshold + " exceeded!");
+ try {
+ mNMService.setInterfaceThrottle(mPolicyIface,
+ mPolicyThrottleValue, mPolicyThrottleValue);
+ } catch (Exception e) {
+ Slog.e(TAG, "error setting Throttle: " + e);
+ }
+
+ mNotificationManager.cancel(com.android.internal.R.drawable.
+ stat_sys_throttle_warning);
+
+ postNotification(com.android.internal.R.string.throttled_notification_title,
+ com.android.internal.R.string.throttled_notification_message,
+ com.android.internal.R.drawable.stat_sys_throttled);
+
+ Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
+ broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, mPolicyThrottleValue);
+ mContext.sendStickyBroadcast(broadcast);
+
+ } // else already up!
+ } else {
+ if ((mPolicyNotificationsAllowedMask & NOTIFICATION_WARNING) != 0) {
+ // check if we should warn about throttle
+ if (currentTotal > (mPolicyThreshold/2) && !mWarningNotificationSent) {
+ mWarningNotificationSent = true;
+ mNotificationManager.cancel(com.android.internal.R.drawable.
+ stat_sys_throttle_warning);
+ postNotification(com.android.internal.R.string.
+ throttle_warning_notification_title,
+ com.android.internal.R.string.
+ throttle_warning_notification_message,
+ com.android.internal.R.drawable.stat_sys_throttle_warning);
+ } else {
+ mWarningNotificationSent =false;
+ }
+ }
+ }
+ }
+
+ private void postNotification(int titleInt, int messageInt, int icon) {
+ Intent intent = new Intent();
+ // TODO - fix up intent
+ intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
+ intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
+
+ PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
+
+ Resources r = Resources.getSystem();
+ CharSequence title = r.getText(titleInt);
+ CharSequence message = r.getText(messageInt);
+ if (mThrottlingNotification == null) {
+ mThrottlingNotification = new Notification();
+ mThrottlingNotification.when = 0;
+ // TODO - fixup icon
+ mThrottlingNotification.icon = icon;
+ mThrottlingNotification.defaults &= ~Notification.DEFAULT_SOUND;
+// mThrottlingNotification.flags = Notification.FLAG_ONGOING_EVENT;
+ }
+ mThrottlingNotification.tickerText = title;
+ mThrottlingNotification.setLatestEventInfo(mContext, title, message, pi);
+
+ mNotificationManager.notify(mThrottlingNotification.icon, mThrottlingNotification);
+ }
+
+
+ private synchronized void clearThrottleAndNotification() {
+ if (mThrottleLevel == 1) {
+ synchronized (ThrottleService.this) {
+ mThrottleLevel = 0;
+ }
+ try {
+ mNMService.setInterfaceThrottle(mPolicyIface, -1, -1);
+ } catch (Exception e) {
+ Slog.e(TAG, "error clearing Throttle: " + e);
+ }
+ Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
+ broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, -1);
+ mContext.sendStickyBroadcast(broadcast);
+ }
+ mNotificationManager.cancel(com.android.internal.R.drawable.stat_sys_throttle_warning);
+ mNotificationManager.cancel(com.android.internal.R.drawable.stat_sys_throttled);
+ mWarningNotificationSent = false;
+ }
+
+ private Calendar calculatePeriodEnd() {
+ Calendar end = GregorianCalendar.getInstance();
+ int day = end.get(Calendar.DAY_OF_MONTH);
+ end.set(Calendar.DAY_OF_MONTH, mPolicyResetDay);
+ end.set(Calendar.HOUR_OF_DAY, 0);
+ end.set(Calendar.MINUTE, 0);
+ if (day >= mPolicyResetDay) {
+ int month = end.get(Calendar.MONTH);
+ if (month == Calendar.DECEMBER) {
+ end.set(Calendar.YEAR, end.get(Calendar.YEAR) + 1);
+ month = Calendar.JANUARY - 1;
+ }
+ end.set(Calendar.MONTH, month + 1);
+ }
+
+ // TODO - remove!
+ if (SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true")) {
+ end = GregorianCalendar.getInstance();
+ end.add(Calendar.SECOND, TESTING_RESET_PERIOD_SEC);
+ }
+ return end;
+ }
+ private Calendar calculatePeriodStart(Calendar end) {
+ Calendar start = (Calendar)end.clone();
+ int month = end.get(Calendar.MONTH);
+ if (end.get(Calendar.MONTH) == Calendar.JANUARY) {
+ month = Calendar.DECEMBER + 1;
+ start.set(Calendar.YEAR, start.get(Calendar.YEAR) - 1);
+ }
+ start.set(Calendar.MONTH, month - 1);
+
+ // TODO - remove!!
+ if (SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true")) {
+ start = (Calendar)end.clone();
+ start.add(Calendar.SECOND, -TESTING_RESET_PERIOD_SEC);
+ }
+ return start;
+ }
+
+ private void onResetAlarm() {
+ if (DBG) {
+ Slog.d(TAG, "onResetAlarm - last period had " + mRecorder.getPeriodRx(0) +
+ " bytes read and " + mRecorder.getPeriodTx(0) + " written");
+ }
+
+ Calendar end = calculatePeriodEnd();
+ Calendar start = calculatePeriodStart(end);
+
+ clearThrottleAndNotification();
+
+ mRecorder.setNextPeriod(start,end);
+
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP, end.getTimeInMillis(),
+ mPendingResetIntent);
+ }
+ }
+
+ // records bytecount data for a given time and accumulates it into larger time windows
+ // for logging and other purposes
+ //
+ // since time can be changed (user or network action) we will have to track the time of the
+ // last recording and deal with it.
+ private static class DataRecorder {
+ long[] mPeriodRxData;
+ long[] mPeriodTxData;
+ int mCurrentPeriod;
+ int mPeriodCount;
+
+ Calendar mPeriodStart;
+ Calendar mPeriodEnd;
+
+ ThrottleService mParent;
+ Context mContext;
+ SharedPreferences mSharedPreferences;
+
+ DataRecorder(Context context, ThrottleService parent) {
+ mContext = context;
+ mParent = parent;
+
+ synchronized (mParent) {
+ mPeriodCount = 6;
+ mPeriodRxData = new long[mPeriodCount];
+ mPeriodTxData = new long[mPeriodCount];
+
+ mPeriodStart = Calendar.getInstance();
+ mPeriodEnd = Calendar.getInstance();
+
+ mSharedPreferences = mContext.getSharedPreferences("ThrottleData",
+ android.content.Context.MODE_PRIVATE);
+
+ zeroData(0);
+ retrieve();
+ }
+ }
+
+ void setNextPeriod(Calendar start, Calendar end) {
+ if (DBG) {
+ Slog.d(TAG, "setting next period to " + start.getTimeInMillis() +
+ " --until-- " + end.getTimeInMillis());
+ }
+ // if we roll back in time to a previous period, toss out the current data
+ // if we roll forward to the next period, advance to the next
+
+ if (end.before(mPeriodStart)) {
+ if (DBG) {
+ Slog.d(TAG, " old start was " + mPeriodStart.getTimeInMillis() + ", wiping");
+ }
+ synchronized (mParent) {
+ mPeriodRxData[mCurrentPeriod] = 0;
+ mPeriodTxData[mCurrentPeriod] = 0;
+ }
+ } else if(start.after(mPeriodEnd)) {
+ if (DBG) {
+ Slog.d(TAG, " old end was " + mPeriodEnd.getTimeInMillis() + ", following");
+ }
+ synchronized (mParent) {
+ ++mCurrentPeriod;
+ if (mCurrentPeriod >= mPeriodCount) mCurrentPeriod = 0;
+ mPeriodRxData[mCurrentPeriod] = 0;
+ mPeriodTxData[mCurrentPeriod] = 0;
+ }
+ } else {
+ if (DBG) Slog.d(TAG, " we fit - ammending to last period");
+ }
+ setPeriodStart(start);
+ setPeriodEnd(end);
+ record();
+ }
+
+ public long getPeriodEnd() {
+ synchronized (mParent) {
+ return mPeriodEnd.getTimeInMillis();
+ }
+ }
+
+ private void setPeriodEnd(Calendar end) {
+ synchronized (mParent) {
+ mPeriodEnd = end;
+ }
+ }
+
+ public long getPeriodStart() {
+ synchronized (mParent) {
+ return mPeriodStart.getTimeInMillis();
+ }
+ }
+
+ private void setPeriodStart(Calendar start) {
+ synchronized (mParent) {
+ mPeriodStart = start;
+ }
+ }
+
+ public int getPeriodCount() {
+ synchronized (mParent) {
+ return mPeriodCount;
+ }
+ }
+
+ private void zeroData(int field) {
+ synchronized (mParent) {
+ for(int period = 0; period<mPeriodCount; period++) {
+ mPeriodRxData[period] = 0;
+ mPeriodTxData[period] = 0;
+ }
+ mCurrentPeriod = 0;
+ }
+
+ }
+
+ // if time moves backward accumulate all read/write that's lost into the now
+ // otherwise time moved forward.
+ void addData(long bytesRead, long bytesWritten) {
+ synchronized (mParent) {
+ mPeriodRxData[mCurrentPeriod] += bytesRead;
+ mPeriodTxData[mCurrentPeriod] += bytesWritten;
+ }
+ record();
+ }
+
+ private void record() {
+ // serialize into a secure setting
+
+ // 1 int mPeriodCount
+ // 13*6 long[PERIOD_COUNT] mPeriodRxData
+ // 13*6 long[PERIOD_COUNT] mPeriodTxData
+ // 1 int mCurrentPeriod
+ // 13 long periodStartMS
+ // 13 long periodEndMS
+ // 199 chars max
+ StringBuilder builder = new StringBuilder();
+ builder.append(mPeriodCount);
+ builder.append(":");
+ for(int i=0; i < mPeriodCount; i++) {
+ builder.append(mPeriodRxData[i]);
+ builder.append(":");
+ }
+ for(int i=0; i < mPeriodCount; i++) {
+ builder.append(mPeriodTxData[i]);
+ builder.append(":");
+ }
+ builder.append(mCurrentPeriod);
+ builder.append(":");
+ builder.append(mPeriodStart.getTimeInMillis());
+ builder.append(":");
+ builder.append(mPeriodEnd.getTimeInMillis());
+ builder.append(":");
+
+ SharedPreferences.Editor editor = mSharedPreferences.edit();
+
+ editor.putString("Data", builder.toString());
+ editor.commit();
+ }
+
+ private void retrieve() {
+ String data = mSharedPreferences.getString("Data", "");
+// String data = Settings.Secure.getString(mContext.getContentResolver(),
+// Settings.Secure.THROTTLE_VALUE);
+ if (data == null || data.length() == 0) return;
+
+ synchronized (mParent) {
+ String[] parsed = data.split(":");
+ int parsedUsed = 0;
+ if (parsed.length < 6) return;
+
+ mPeriodCount = Integer.parseInt(parsed[parsedUsed++]);
+ if (parsed.length != 4 + (2 * mPeriodCount)) return;
+
+ mPeriodRxData = new long[mPeriodCount];
+ for(int i=0; i < mPeriodCount; i++) {
+ mPeriodRxData[i] = Long.parseLong(parsed[parsedUsed++]);
+ }
+ mPeriodTxData = new long[mPeriodCount];
+ for(int i=0; i < mPeriodCount; i++) {
+ mPeriodTxData[i] = Long.parseLong(parsed[parsedUsed++]);
+ }
+ mCurrentPeriod = Integer.parseInt(parsed[parsedUsed++]);
+ mPeriodStart = new GregorianCalendar();
+ mPeriodStart.setTimeInMillis(Long.parseLong(parsed[parsedUsed++]));
+ mPeriodEnd = new GregorianCalendar();
+ mPeriodEnd.setTimeInMillis(Long.parseLong(parsed[parsedUsed++]));
+ }
+ }
+
+ long getPeriodRx(int which) {
+ if (DBG) { // TODO - remove
+ Slog.d(TAG, "reading slot "+ which +" with current =" + mCurrentPeriod);
+ for(int x = 0; x<mPeriodCount; x++) {
+ Slog.d(TAG, " " + x + " = " + mPeriodRxData[x]);
+ }
+ }
+ synchronized (mParent) {
+ if (which > mPeriodCount) return 0;
+ which = mCurrentPeriod - which;
+ if (which < 0) which += mPeriodCount;
+ return mPeriodRxData[which];
+ }
+ }
+ long getPeriodTx(int which) {
+ synchronized (mParent) {
+ if (which > mPeriodCount) return 0;
+ which = mCurrentPeriod - which;
+ if (which < 0) which += mPeriodCount;
+ return mPeriodTxData[which];
+ }
+ }
+ }
+
+ @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 ThrottleService " +
+ "from from pid=" + Binder.getCallingPid() + ", uid=" +
+ Binder.getCallingUid());
+ return;
+ }
+ pw.println();
+
+ pw.println("The threshold is " + mPolicyThreshold +
+ ", after which you experince throttling to " +
+ mPolicyThrottleValue + "kbps");
+ pw.println("Current period is " +
+ (mRecorder.getPeriodEnd() - mRecorder.getPeriodStart())/1000 + " seconds long " +
+ "and ends in " + (mRecorder.getPeriodEnd() - System.currentTimeMillis()) / 1000 +
+ " seconds.");
+ pw.println("Polling every " + mPolicyPollPeriodSec + " seconds");
+ for (int i = 0; i < mRecorder.getPeriodCount(); i++) {
+ pw.println(" Period[" + i + "] - read:" + mRecorder.getPeriodRx(i) + ", written:" +
+ mRecorder.getPeriodTx(i));
+ }
+ }
+}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3b655fa..bc26fa0 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1369,7 +1369,7 @@
return;
}
} else {
- procs = service.mLruProcesses;
+ procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
}
}
dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
@@ -10202,7 +10202,7 @@
return numPers;
}
- private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
+ static final void dumpApplicationMemoryUsage(FileDescriptor fd,
PrintWriter pw, List list, String prefix, String[] args) {
final boolean isCheckinRequest = scanArgs(args, "--checkin");
long uptime = SystemClock.uptimeMillis();
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 55840e2..465ff2e 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -818,7 +818,7 @@
final ContentResolver cr = mContext.getContentResolver();
if (Settings.System.getInt(cr,
- Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
+ Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
{
final String soundPath = Settings.System.getString(cr,
Settings.System.LOW_BATTERY_SOUND);
@@ -972,7 +972,8 @@
int iconLevel = -1;
int[] iconList;
- if (!hasService()) {
+ // Display signal strength while in "emergency calls only" mode
+ if (!hasService() && !mServiceState.isEmergencyOnly()) {
//Slog.d(TAG, "updateSignalStrength: no service");
if (Settings.System.getInt(mContext.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 48a40fa..6c66559 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -113,6 +113,8 @@
private String mOperatorNumeric;
private boolean mIsManualNetworkSelection;
+ private boolean mIsEmergencyOnly;
+
//***** CDMA
private int mRadioTechnology;
private boolean mCssIndicator;
@@ -170,6 +172,7 @@
mCdmaDefaultRoamingIndicator = s.mCdmaDefaultRoamingIndicator;
mCdmaEriIconIndex = s.mCdmaEriIconIndex;
mCdmaEriIconMode = s.mCdmaEriIconMode;
+ mIsEmergencyOnly = s.mIsEmergencyOnly;
}
/**
@@ -190,6 +193,7 @@
mCdmaDefaultRoamingIndicator = in.readInt();
mCdmaEriIconIndex = in.readInt();
mCdmaEriIconMode = in.readInt();
+ mIsEmergencyOnly = in.readInt() != 0;
}
public void writeToParcel(Parcel out, int flags) {
@@ -207,6 +211,7 @@
out.writeInt(mCdmaDefaultRoamingIndicator);
out.writeInt(mCdmaEriIconIndex);
out.writeInt(mCdmaEriIconMode);
+ out.writeInt(mIsEmergencyOnly ? 1 : 0);
}
public int describeContents() {
@@ -250,6 +255,13 @@
/**
* @hide
*/
+ public boolean isEmergencyOnly() {
+ return mIsEmergencyOnly;
+ }
+
+ /**
+ * @hide
+ */
public int getCdmaRoamingIndicator(){
return this.mCdmaRoamingIndicator;
}
@@ -330,7 +342,8 @@
+ ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode())
+ ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode())
+ mCdmaRoamingIndicator
- + mCdmaDefaultRoamingIndicator);
+ + mCdmaDefaultRoamingIndicator
+ + (mIsEmergencyOnly ? 1 : 0));
}
@Override
@@ -359,7 +372,8 @@
&& equalsHandlesNulls(mSystemId, s.mSystemId)
&& equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
&& equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
- s.mCdmaDefaultRoamingIndicator));
+ s.mCdmaDefaultRoamingIndicator)
+ && mIsEmergencyOnly == s.mIsEmergencyOnly);
}
@Override
@@ -418,7 +432,8 @@
+ " " + mNetworkId
+ " " + mSystemId
+ "RoamInd: " + mCdmaRoamingIndicator
- + "DefRoamInd: " + mCdmaDefaultRoamingIndicator);
+ + "DefRoamInd: " + mCdmaDefaultRoamingIndicator
+ + "EmergOnly: " + mIsEmergencyOnly);
}
public void setStateOutOfService() {
@@ -436,6 +451,7 @@
mCdmaDefaultRoamingIndicator = -1;
mCdmaEriIconIndex = -1;
mCdmaEriIconMode = -1;
+ mIsEmergencyOnly = false;
}
// TODO - can't this be combined with the above func..
@@ -454,6 +470,7 @@
mCdmaDefaultRoamingIndicator = -1;
mCdmaEriIconIndex = -1;
mCdmaEriIconMode = -1;
+ mIsEmergencyOnly = false;
}
public void setState(int state) {
@@ -464,6 +481,14 @@
mRoaming = roaming;
}
+
+ /**
+ * @hide
+ */
+ public void setEmergencyOnly(boolean emergencyOnly) {
+ mIsEmergencyOnly = emergencyOnly;
+ }
+
/**
* @hide
*/
@@ -542,6 +567,7 @@
mSystemId = m.getInt("systemId");
mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
+ mIsEmergencyOnly = m.getBoolean("emergencyOnly");
}
/**
@@ -563,6 +589,7 @@
m.putInt("systemId", mSystemId);
m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
+ m.putBoolean("emergencyOnly", Boolean.valueOf(mIsEmergencyOnly));
}
//***** CDMA
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index e4fcf6c..50b8eba 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -102,7 +102,6 @@
* Mark when service state is in emergency call only mode
*/
private boolean mEmergencyOnly = false;
- private boolean mNewEmergencyOnly = false;
private RegistrantList gprsAttachedRegistrants = new RegistrantList();
private RegistrantList gprsDetachedRegistrants = new RegistrantList();
@@ -591,8 +590,8 @@
if (rule != curSpnRule
|| !TextUtils.equals(spn, curSpn)
|| !TextUtils.equals(plmn, curPlmn)) {
- boolean showSpn = mEmergencyOnly
- || (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
+ boolean showSpn = !mEmergencyOnly
+ && (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
boolean showPlmn =
(rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
@@ -672,9 +671,9 @@
newSS.setState (regCodeToServiceState(regState));
if (regState == 10 || regState == 12 || regState == 13 || regState == 14) {
- mNewEmergencyOnly = true;
+ mEmergencyOnly = true;
} else {
- mNewEmergencyOnly = false;
+ mEmergencyOnly = false;
}
// LAC and CID are -1 if not avail
@@ -741,6 +740,7 @@
roaming = false;
}
newSS.setRoaming(roaming);
+ newSS.setEmergencyOnly(mEmergencyOnly);
pollStateDone();
}
}
@@ -886,8 +886,6 @@
boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
- boolean hasEmergencyOnlyChanged = mNewEmergencyOnly != mEmergencyOnly;
-
// Add an event log when connection state changes
if (ss.getState() != newSS.getState() || gprsState != newGPRSState) {
EventLog.writeEvent(EventLogTags.GSM_SERVICE_STATE_CHANGE,
@@ -905,8 +903,6 @@
cellLoc = newCellLoc;
newCellLoc = tcl;
- mEmergencyOnly = mNewEmergencyOnly;
-
// Add an event log when network type switched
// TODO: we may add filtering to reduce the event logged,
// i.e. check preferred network setting, only switch to 2G, etc
@@ -937,6 +933,8 @@
if (hasChanged) {
String operatorNumeric;
+ updateSpnDisplay();
+
phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
ss.getOperatorAlphaLong());
@@ -1005,10 +1003,6 @@
phone.notifyServiceStateChanged(ss);
}
- if (hasChanged || hasEmergencyOnlyChanged) {
- updateSpnDisplay();
- }
-
if (hasGprsAttached) {
gprsAttachedRegistrants.notifyRegistrants();
}