Merge "Fix Tethering when DUN is required but wifi is ok"
diff --git a/api/current.xml b/api/current.xml
index 9dc2218..58ce3ee 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -26873,11 +26873,22 @@
visibility="public"
>
</field>
+<field name="PASSWORD_QUALITY_ALPHABETIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="262144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="PASSWORD_QUALITY_ALPHANUMERIC"
type="int"
transient="false"
volatile="false"
- value="196608"
+ value="327680"
static="true"
final="true"
deprecated="not deprecated"
@@ -80658,6 +80669,19 @@
<parameter name="l" type="android.media.AudioManager.OnAudioFocusChangeListener">
</parameter>
</method>
+<method name="registerMediaButtonEventReceiver"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventReceiver" type="android.content.ComponentName">
+</parameter>
+</method>
<method name="requestAudioFocus"
return="int"
abstract="false"
@@ -80917,6 +80941,19 @@
<parameter name="l" type="android.media.AudioManager.OnAudioFocusChangeListener">
</parameter>
</method>
+<method name="unregisterMediaButtonEventReceiver"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventReceiver" type="android.content.ComponentName">
+</parameter>
+</method>
<field name="ACTION_AUDIO_BECOMING_NOISY"
type="java.lang.String"
transient="false"
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index cfc2e75..659d70f 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -92,11 +92,6 @@
return;
}
- if ("mountsd".equals(op)) {
- runMountSd();
- return;
- }
-
if ("uninstall".equals(op)) {
runUninstall();
return;
@@ -646,37 +641,6 @@
}
}
- private void runMountSd() {
- String opt;
- boolean mount = false;
- while ((opt=nextOption()) != null) {
- if (opt.equals("-m")) {
- String mountStr = nextOptionData();
- if (mountStr == null) {
- System.err.println("Error: no value specified for -m");
- showUsage();
- return;
- }
- if ("true".equalsIgnoreCase(mountStr)) {
- mount = true;
- } else if ("false".equalsIgnoreCase(mountStr)) {
- mount = false;
- } else {
- System.err.println("Error: no value specified for -m");
- showUsage();
- return;
- }
- }
- }
-
- try {
- mPm.updateExternalMediaStatus(mount);
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- }
- }
-
class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
boolean finished;
boolean result;
@@ -866,7 +830,6 @@
System.err.println(" pm path PACKAGE");
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
System.err.println(" pm uninstall [-k] PACKAGE");
- System.err.println(" pm mountsd [-m true/false]");
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
System.err.println(" pm disable PACKAGE_OR_COMPONENT");
System.err.println("");
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6d5686a..596ca9d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -980,10 +980,11 @@
return true;
}
- case KILL_PIDS_FOR_MEMORY_TRANSACTION: {
+ case KILL_PIDS_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int[] pids = data.createIntArray();
- boolean res = killPidsForMemory(pids);
+ String reason = data.readString();
+ boolean res = killPids(pids, reason);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -2393,12 +2394,13 @@
mRemote.transact(NOTE_WAKEUP_ALARM_TRANSACTION, data, null, 0);
data.recycle();
}
- public boolean killPidsForMemory(int[] pids) throws RemoteException {
+ public boolean killPids(int[] pids, String reason) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeIntArray(pids);
- mRemote.transact(KILL_PIDS_FOR_MEMORY_TRANSACTION, data, reply, 0);
+ data.writeString(reason);
+ mRemote.transact(KILL_PIDS_TRANSACTION, data, reply, 0);
boolean res = reply.readInt() != 0;
data.recycle();
reply.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 14571de..30feae1 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -241,7 +241,7 @@
public void noteWakeupAlarm(IIntentSender sender) throws RemoteException;
- public boolean killPidsForMemory(int[] pids) throws RemoteException;
+ public boolean killPids(int[] pids, String reason) throws RemoteException;
public void reportPss(IApplicationThread caller, int pss) throws RemoteException;
@@ -476,7 +476,7 @@
int GET_PROCESSES_IN_ERROR_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+76;
int CLEAR_APP_DATA_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+77;
int FORCE_STOP_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78;
- int KILL_PIDS_FOR_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79;
+ int KILL_PIDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79;
int GET_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+80;
int REPORT_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81;
int GET_RUNNING_APP_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+82;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2d9b415..35e7ee6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -20,7 +20,6 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.app.admin.IDevicePolicyManager.Stub;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -192,11 +191,19 @@
/**
* Constant for {@link #setPasswordQuality}: the user must have entered a
+ * password containing at least alphabetic (or other symbol) characters.
+ * Note that quality constants are ordered so that higher values are more
+ * restrictive.
+ */
+ public static final int PASSWORD_QUALITY_ALPHABETIC = 0x40000;
+
+ /**
+ * Constant for {@link #setPasswordQuality}: the user must have entered a
* password containing at least <em>both></em> numeric <em>and</em>
- * alphabeter (or other symbol) characters. Note that quality constants are
+ * alphabetic (or other symbol) characters. Note that quality constants are
* ordered so that higher values are more restrictive.
*/
- public static final int PASSWORD_QUALITY_ALPHANUMERIC = 0x30000;
+ public static final int PASSWORD_QUALITY_ALPHANUMERIC = 0x50000;
/**
* Called by an application that is administering the device to set the
@@ -219,7 +226,8 @@
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param quality The new desired quality. One of
* {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING},
- * {@link #PASSWORD_QUALITY_NUMERIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC}.
+ * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC},
+ * or {@link #PASSWORD_QUALITY_ALPHANUMERIC}.
*/
public void setPasswordQuality(ComponentName admin, int quality) {
if (mService != null) {
@@ -257,7 +265,8 @@
* take place immediately. To prompt the user for a new password, use
* {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested either
- * {@link #PASSWORD_QUALITY_NUMERIC} or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
+ * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC},
+ * or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
* with {@link #setPasswordQuality}.
*
* <p>The calling device admin must have requested
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 399a87d..c638d04 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -309,7 +309,7 @@
* MountService uses this to call into the package manager to update
* status of sdcard.
*/
- boolean updateExternalMediaStatus(boolean mounted);
+ void updateExternalMediaStatus(boolean mounted, boolean reportStatus);
String nextPackageToClean(String lastPackage);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bbf4ca1..0318b6c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -233,7 +233,7 @@
/**
* Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
* indicate that this package should be installed as forward locked, i.e. only the app itself
- * should have access to it's code and non-resource assets.
+ * should have access to its code and non-resource assets.
* @hide
*/
public static final int INSTALL_FORWARD_LOCK = 0x00000001;
diff --git a/core/java/android/database/MergeCursor.java b/core/java/android/database/MergeCursor.java
index 7e91159..722d707 100644
--- a/core/java/android/database/MergeCursor.java
+++ b/core/java/android/database/MergeCursor.java
@@ -185,6 +185,7 @@
mCursors[i].deactivate();
}
}
+ super.deactivate();
}
@Override
@@ -194,6 +195,7 @@
if (mCursors[i] == null) continue;
mCursors[i].close();
}
+ super.close();
}
@Override
diff --git a/core/java/android/hardware/GeomagneticField.java b/core/java/android/hardware/GeomagneticField.java
index b4c04b1..96fbe77 100644
--- a/core/java/android/hardware/GeomagneticField.java
+++ b/core/java/android/hardware/GeomagneticField.java
@@ -26,8 +26,9 @@
* <p>This uses the World Magnetic Model produced by the United States National
* Geospatial-Intelligence Agency. More details about the model can be found at
* <a href="http://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml">http://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml</a>.
- * This class currently uses WMM-2005 which is valid until 2010, but should
- * produce acceptable results for several years after that.
+ * This class currently uses WMM-2010 which is valid until 2015, but should
+ * produce acceptable results for several years after that. Future versions of
+ * Android may use a newer version of the model.
*/
public class GeomagneticField {
// The magnetic field at a given point, in nonoteslas in geodetic
@@ -43,75 +44,73 @@
// Constants from WGS84 (the coordinate system used by GPS)
static private final float EARTH_SEMI_MAJOR_AXIS_KM = 6378.137f;
- static private final float EARTH_SEMI_MINOR_AXIS_KM = 6356.7523f;
+ static private final float EARTH_SEMI_MINOR_AXIS_KM = 6356.7523142f;
static private final float EARTH_REFERENCE_RADIUS_KM = 6371.2f;
// These coefficients and the formulae used below are from:
- // NOAA Technical Report: The US/UK World Magnetic Model for 2005-2010
+ // NOAA Technical Report: The US/UK World Magnetic Model for 2010-2015
static private final float[][] G_COEFF = new float[][] {
- { 0f },
- { -29556.8f, -1671.7f },
- { -2340.6f, 3046.9f, 1657.0f },
- { 1335.4f, -2305.1f, 1246.7f, 674.0f },
- { 919.8f, 798.1f, 211.3f, -379.4f, 100.0f },
- { -227.4f, 354.6f, 208.7f, -136.5f, -168.3f, -14.1f },
- { 73.2f, 69.7f, 76.7f, -151.2f, -14.9f, 14.6f, -86.3f },
- { 80.1f, -74.5f, -1.4f, 38.5f, 12.4f, 9.5f, 5.7f, 1.8f },
- { 24.9f, 7.7f, -11.6f, -6.9f, -18.2f, 10.0f, 9.2f, -11.6f, -5.2f },
- { 5.6f, 9.9f, 3.5f, -7.0f, 5.1f, -10.8f, -1.3f, 8.8f, -6.7f, -9.1f },
- { -2.3f, -6.3f, 1.6f, -2.6f, 0.0f, 3.1f, 0.4f, 2.1f, 3.9f, -0.1f, -2.3f },
- { 2.8f, -1.6f, -1.7f, 1.7f, -0.1f, 0.1f, -0.7f, 0.7f, 1.8f, 0.0f, 1.1f, 4.1f },
- { -2.4f, -0.4f, 0.2f, 0.8f, -0.3f, 1.1f, -0.5f, 0.4f, -0.3f, -0.3f, -0.1f,
- -0.3f, -0.1f } };
+ { 0.0f },
+ { -29496.6f, -1586.3f },
+ { -2396.6f, 3026.1f, 1668.6f },
+ { 1340.1f, -2326.2f, 1231.9f, 634.0f },
+ { 912.6f, 808.9f, 166.7f, -357.1f, 89.4f },
+ { -230.9f, 357.2f, 200.3f, -141.1f, -163.0f, -7.8f },
+ { 72.8f, 68.6f, 76.0f, -141.4f, -22.8f, 13.2f, -77.9f },
+ { 80.5f, -75.1f, -4.7f, 45.3f, 13.9f, 10.4f, 1.7f, 4.9f },
+ { 24.4f, 8.1f, -14.5f, -5.6f, -19.3f, 11.5f, 10.9f, -14.1f, -3.7f },
+ { 5.4f, 9.4f, 3.4f, -5.2f, 3.1f, -12.4f, -0.7f, 8.4f, -8.5f, -10.1f },
+ { -2.0f, -6.3f, 0.9f, -1.1f, -0.2f, 2.5f, -0.3f, 2.2f, 3.1f, -1.0f, -2.8f },
+ { 3.0f, -1.5f, -2.1f, 1.7f, -0.5f, 0.5f, -0.8f, 0.4f, 1.8f, 0.1f, 0.7f, 3.8f },
+ { -2.2f, -0.2f, 0.3f, 1.0f, -0.6f, 0.9f, -0.1f, 0.5f, -0.4f, -0.4f, 0.2f, -0.8f, 0.0f } };
static private final float[][] H_COEFF = new float[][] {
- { 0f },
- { 0.0f, 5079.8f },
- { 0.0f, -2594.7f, -516.7f },
- { 0.0f, -199.9f, 269.3f, -524.2f },
- { 0.0f, 281.5f, -226.0f, 145.8f, -304.7f },
- { 0.0f, 42.4f, 179.8f, -123.0f, -19.5f, 103.6f },
- { 0.0f, -20.3f, 54.7f, 63.6f, -63.4f, -0.1f, 50.4f },
- { 0.0f, -61.5f, -22.4f, 7.2f, 25.4f, 11.0f, -26.4f, -5.1f },
- { 0.0f, 11.2f, -21.0f, 9.6f, -19.8f, 16.1f, 7.7f, -12.9f, -0.2f },
- { 0.0f, -20.1f, 12.9f, 12.6f, -6.7f, -8.1f, 8.0f, 2.9f, -7.9f, 6.0f },
- { 0.0f, 2.4f, 0.2f, 4.4f, 4.8f, -6.5f, -1.1f, -3.4f, -0.8f, -2.3f, -7.9f },
- { 0.0f, 0.3f, 1.2f, -0.8f, -2.5f, 0.9f, -0.6f, -2.7f, -0.9f, -1.3f, -2.0f, -1.2f },
- { 0.0f, -0.4f, 0.3f, 2.4f, -2.6f, 0.6f, 0.3f, 0.0f, 0.0f, 0.3f, -0.9f, -0.4f,
- 0.8f } };
+ { 0.0f },
+ { 0.0f, 4944.4f },
+ { 0.0f, -2707.7f, -576.1f },
+ { 0.0f, -160.2f, 251.9f, -536.6f },
+ { 0.0f, 286.4f, -211.2f, 164.3f, -309.1f },
+ { 0.0f, 44.6f, 188.9f, -118.2f, 0.0f, 100.9f },
+ { 0.0f, -20.8f, 44.1f, 61.5f, -66.3f, 3.1f, 55.0f },
+ { 0.0f, -57.9f, -21.1f, 6.5f, 24.9f, 7.0f, -27.7f, -3.3f },
+ { 0.0f, 11.0f, -20.0f, 11.9f, -17.4f, 16.7f, 7.0f, -10.8f, 1.7f },
+ { 0.0f, -20.5f, 11.5f, 12.8f, -7.2f, -7.4f, 8.0f, 2.1f, -6.1f, 7.0f },
+ { 0.0f, 2.8f, -0.1f, 4.7f, 4.4f, -7.2f, -1.0f, -3.9f, -2.0f, -2.0f, -8.3f },
+ { 0.0f, 0.2f, 1.7f, -0.6f, -1.8f, 0.9f, -0.4f, -2.5f, -1.3f, -2.1f, -1.9f, -1.8f },
+ { 0.0f, -0.9f, 0.3f, 2.1f, -2.5f, 0.5f, 0.6f, 0.0f, 0.1f, 0.3f, -0.9f, -0.2f, 0.9f } };
static private final float[][] DELTA_G = new float[][] {
- { 0f },
- { 8.0f, 10.6f },
- { -15.1f, -7.8f, -0.8f },
- { 0.4f, -2.6f, -1.2f, -6.5f },
- { -2.5f, 2.8f, -7.0f, 6.2f, -3.8f },
- { -2.8f, 0.7f, -3.2f, -1.1f, 0.1f, -0.8f },
- { -0.7f, 0.4f, -0.3f, 2.3f, -2.1f, -0.6f, 1.4f },
- { 0.2f, -0.1f, -0.3f, 1.1f, 0.6f, 0.5f, -0.4f, 0.6f },
- { 0.1f, 0.3f, -0.4f, 0.3f, -0.3f, 0.2f, 0.4f, -0.7f, 0.4f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } };
+ { 0.0f },
+ { 11.6f, 16.5f },
+ { -12.1f, -4.4f, 1.9f },
+ { 0.4f, -4.1f, -2.9f, -7.7f },
+ { -1.8f, 2.3f, -8.7f, 4.6f, -2.1f },
+ { -1.0f, 0.6f, -1.8f, -1.0f, 0.9f, 1.0f },
+ { -0.2f, -0.2f, -0.1f, 2.0f, -1.7f, -0.3f, 1.7f },
+ { 0.1f, -0.1f, -0.6f, 1.3f, 0.4f, 0.3f, -0.7f, 0.6f },
+ { -0.1f, 0.1f, -0.6f, 0.2f, -0.2f, 0.3f, 0.3f, -0.6f, 0.2f },
+ { 0.0f, -0.1f, 0.0f, 0.3f, -0.4f, -0.3f, 0.1f, -0.1f, -0.4f, -0.2f },
+ { 0.0f, 0.0f, -0.1f, 0.2f, 0.0f, -0.1f, -0.2f, 0.0f, -0.1f, -0.2f, -0.2f },
+ { 0.0f, 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.1f, 0.0f },
+ { 0.0f, 0.0f, 0.1f, 0.1f, -0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.1f, 0.1f } };
static private final float[][] DELTA_H = new float[][] {
- { 0f },
- { 0.0f, -20.9f },
- { 0.0f, -23.2f, -14.6f },
- { 0.0f, 5.0f, -7.0f, -0.6f },
- { 0.0f, 2.2f, 1.6f, 5.8f, 0.1f },
- { 0.0f, 0.0f, 1.7f, 2.1f, 4.8f, -1.1f },
- { 0.0f, -0.6f, -1.9f, -0.4f, -0.5f, -0.3f, 0.7f },
- { 0.0f, 0.6f, 0.4f, 0.2f, 0.3f, -0.8f, -0.2f, 0.1f },
- { 0.0f, -0.2f, 0.1f, 0.3f, 0.4f, 0.1f, -0.2f, 0.4f, 0.4f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } };
+ { 0.0f },
+ { 0.0f, -25.9f },
+ { 0.0f, -22.5f, -11.8f },
+ { 0.0f, 7.3f, -3.9f, -2.6f },
+ { 0.0f, 1.1f, 2.7f, 3.9f, -0.8f },
+ { 0.0f, 0.4f, 1.8f, 1.2f, 4.0f, -0.6f },
+ { 0.0f, -0.2f, -2.1f, -0.4f, -0.6f, 0.5f, 0.9f },
+ { 0.0f, 0.7f, 0.3f, -0.1f, -0.1f, -0.8f, -0.3f, 0.3f },
+ { 0.0f, -0.1f, 0.2f, 0.4f, 0.4f, 0.1f, -0.1f, 0.4f, 0.3f },
+ { 0.0f, 0.0f, -0.2f, 0.0f, -0.1f, 0.1f, 0.0f, -0.2f, 0.3f, 0.2f },
+ { 0.0f, 0.1f, -0.1f, 0.0f, -0.1f, -0.1f, 0.0f, -0.1f, -0.2f, 0.0f, -0.1f },
+ { 0.0f, 0.0f, 0.1f, 0.0f, 0.1f, 0.0f, 0.1f, 0.0f, -0.1f, -0.1f, 0.0f, -0.1f },
+ { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } };
static private final long BASE_TIME =
- new GregorianCalendar(2005, 1, 1).getTimeInMillis();
+ new GregorianCalendar(2010, 1, 1).getTimeInMillis();
// The ratio between the Gauss-normalized associated Legendre functions and
// the Schmid quasi-normalized ones. Compute these once staticly since they
@@ -191,7 +190,7 @@
// We now compute the magnetic field strength given the geocentric
// location. The magnetic field is the derivative of the potential
// function defined by the model. See NOAA Technical Report: The US/UK
- // World Magnetic Model for 2005-2010 for the derivation.
+ // World Magnetic Model for 2010-2015 for the derivation.
float gcX = 0.0f; // Geocentric northwards component.
float gcY = 0.0f; // Geocentric eastwards component.
float gcZ = 0.0f; // Geocentric downwards component.
@@ -406,4 +405,4 @@
}
return schmidtQuasiNorm;
}
-}
\ No newline at end of file
+}
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index f2ea539..eca4569 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1598,6 +1598,8 @@
end = query.length();
}
return decode(query.substring(equalsIndex + 1, end));
+ } else {
+ encodedKeySearchIndex = equalsIndex + 1;
}
}
return null;
diff --git a/core/java/android/net/http/Request.java b/core/java/android/net/http/Request.java
index 1b6568e..6dbf325 100644
--- a/core/java/android/net/http/Request.java
+++ b/core/java/android/net/http/Request.java
@@ -82,6 +82,9 @@
/* Used to synchronize waitUntilComplete() requests */
private final Object mClientResource = new Object();
+ /** True if loading should be paused **/
+ private boolean mLoadingPaused = false;
+
/**
* Processor used to set content-length and transfer-encoding
* headers.
@@ -133,6 +136,18 @@
}
/**
+ * @param pause True if the load should be paused.
+ */
+ synchronized void setLoadingPaused(boolean pause) {
+ mLoadingPaused = pause;
+
+ // Wake up the paused thread if we're unpausing the load.
+ if (!mLoadingPaused) {
+ notify();
+ }
+ }
+
+ /**
* @param connection Request served by this connection
*/
void setConnection(Connection connection) {
@@ -271,7 +286,24 @@
int len = 0;
int lowWater = buf.length / 2;
while (len != -1) {
+ synchronized(this) {
+ while (mLoadingPaused) {
+ // Put this (network loading) thread to sleep if WebCore
+ // has asked us to. This can happen with plugins for
+ // example, if we are streaming data but the plugin has
+ // filled its internal buffers.
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ HttpLog.e("Interrupted exception whilst "
+ + "network thread paused at WebCore's request."
+ + " " + e.getMessage());
+ }
+ }
+ }
+
len = nis.read(buf, count, buf.length - count);
+
if (len != -1) {
count += len;
}
@@ -316,10 +348,16 @@
*
* Called by RequestHandle from non-network thread
*/
- void cancel() {
+ synchronized void cancel() {
if (HttpLog.LOGV) {
HttpLog.v("Request.cancel(): " + getUri());
}
+
+ // Ensure that the network thread is not blocked by a hanging request from WebCore to
+ // pause the load.
+ mLoadingPaused = false;
+ notify();
+
mCancelled = true;
if (mConnection != null) {
mConnection.cancel();
diff --git a/core/java/android/net/http/RequestHandle.java b/core/java/android/net/http/RequestHandle.java
index 77cd544..1a3a289 100644
--- a/core/java/android/net/http/RequestHandle.java
+++ b/core/java/android/net/http/RequestHandle.java
@@ -101,6 +101,16 @@
}
/**
+ * Pauses the loading of this request. For example, called from the WebCore thread
+ * when the plugin can take no more data.
+ */
+ public void pauseRequest(boolean pause) {
+ if (mRequest != null) {
+ mRequest.setLoadingPaused(pause);
+ }
+ }
+
+ /**
* Handles SSL error(s) on the way down from the user (the user
* has already provided their feedback).
*/
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index e4eaf45b..f4ca8bc 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -361,6 +361,9 @@
*/
public WakeLock newWakeLock(int flags, String tag)
{
+ if (tag == null) {
+ throw new NullPointerException("tag is null in PowerManager.newWakeLock");
+ }
return new WakeLock(flags, tag);
}
diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl
index 75455ab..4862f80 100644
--- a/core/java/android/os/storage/IMountService.aidl
+++ b/core/java/android/os/storage/IMountService.aidl
@@ -84,7 +84,7 @@
int[] getStorageUsers(String path);
/**
- * Gets the state of an volume via it's mountpoint.
+ * Gets the state of a volume via its mountpoint.
*/
String getVolumeState(String mountPoint);
@@ -146,4 +146,10 @@
* Invokes call back once the shutdown is complete.
*/
void shutdown(IMountShutdownObserver observer);
+
+ /**
+ * Call into MountService by PackageManager to notify that its done
+ * processing the media status update request.
+ */
+ void finishMediaUpdate();
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 53c238c..c44854a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -506,6 +506,17 @@
updateWindow(false);
}
+ /**
+ * Check to see if the surface has fixed size dimensions or if the surface's
+ * dimensions are dimensions are dependent on its current layout.
+ *
+ * @return true if the surface has dimensions that are fixed in size
+ * @hide
+ */
+ public boolean isFixedSize() {
+ return (mRequestedWidth != -1 || mRequestedHeight != -1);
+ }
+
private static class MyWindow extends BaseIWindow {
private final WeakReference<SurfaceView> mSurfaceView;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 2b5489c..d2563a8 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -1040,7 +1040,7 @@
clientStream.writeInt(outRect.width());
clientStream.writeInt(outRect.height());
- captureViewLayer(root, clientStream);
+ captureViewLayer(root, clientStream, true);
clientStream.write(2);
} finally {
@@ -1048,9 +1048,11 @@
}
}
- private static void captureViewLayer(View view, DataOutputStream clientStream)
+ private static void captureViewLayer(View view, DataOutputStream clientStream, boolean visible)
throws IOException {
+ final boolean localVisible = view.getVisibility() == View.VISIBLE && visible;
+
if ((view.mPrivateFlags & View.SKIP_DRAW) != View.SKIP_DRAW) {
final int id = view.getId();
String name = view.getClass().getSimpleName();
@@ -1060,7 +1062,7 @@
clientStream.write(1);
clientStream.writeUTF(name);
- clientStream.writeByte(view.getVisibility() == View.VISIBLE ? 1 : 0);
+ clientStream.writeByte(localVisible ? 1 : 0);
int[] position = new int[2];
// XXX: Should happen on the UI thread
@@ -1086,7 +1088,7 @@
int count = group.getChildCount();
for (int i = 0; i < count; i++) {
- captureViewLayer(group.getChildAt(i), clientStream);
+ captureViewLayer(group.getChildAt(i), clientStream, localVisible);
}
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 597d583..006aff8 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1274,13 +1274,27 @@
@Override
Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
- int oldCount = mChildrenCount;
+ int count = mChildrenCount;
+ int[] visibilities = null;
+
if (skipChildren) {
- mChildrenCount = 0;
+ visibilities = new int[count];
+ for (int i = 0; i < count; i++) {
+ View child = getChildAt(i);
+ visibilities[i] = child.getVisibility();
+ if (visibilities[i] == View.VISIBLE) {
+ child.setVisibility(INVISIBLE);
+ }
+ }
}
Bitmap b = super.createSnapshot(quality, backgroundColor, skipChildren);
- mChildrenCount = oldCount;
+
+ if (skipChildren) {
+ for (int i = 0; i < count; i++) {
+ getChildAt(i).setVisibility(visibilities[i]);
+ }
+ }
return b;
}
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index dc7723f..2c24757 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -1198,6 +1198,16 @@
}
/**
+ * Pause the load. For example, if a plugin is unable to accept more data,
+ * we pause reading from the request. Called directly from the WebCore thread.
+ */
+ void pauseLoad(boolean pause) {
+ if (mRequestHandle != null) {
+ mRequestHandle.pauseRequest(pause);
+ }
+ }
+
+ /**
* Cancel a request.
* FIXME: This will only work if the request has yet to be handled. This
* is in no way guarenteed if requests are served in a separate thread.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index cabda85..784f886 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2618,6 +2618,9 @@
* @hide
*/
public void notifyFindDialogDismissed() {
+ if (mWebViewCore == null) {
+ return;
+ }
clearMatches();
setFindIsUp(false);
recordNewContentSize(mContentWidth, mContentHeight - mFindHeight,
@@ -4192,7 +4195,15 @@
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
- sendOurVisibleRect();
+ if (!mInOverScrollMode) {
+ sendOurVisibleRect();
+ // update WebKit if visible title bar height changed. The logic is same
+ // as getVisibleTitleHeight.
+ int titleHeight = getTitleHeight();
+ if (Math.max(titleHeight - t, 0) != Math.max(titleHeight - oldt, 0)) {
+ sendViewSizeZoom();
+ }
+ }
}
@Override
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index a870931..a75e6f0 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -389,10 +389,17 @@
return false;
}
- Cursor cursor = mDatabase.query(mTableNames[tableId], ID_PROJECTION,
- null, null, null, null, null);
- boolean ret = cursor.moveToFirst() == true;
- cursor.close();
+ Cursor cursor = null;
+ boolean ret = false;
+ try {
+ cursor = mDatabase.query(mTableNames[tableId], ID_PROJECTION,
+ null, null, null, null, null);
+ ret = cursor.moveToFirst() == true;
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "hasEntries", e);
+ } finally {
+ if (cursor != null) cursor.close();
+ }
return ret;
}
@@ -420,33 +427,39 @@
};
final String selection = "(" + COOKIES_DOMAIN_COL
+ " GLOB '*' || ?)";
- Cursor cursor = mDatabase.query(mTableNames[TABLE_COOKIES_ID],
- columns, selection, new String[] { domain }, null, null,
- null);
- if (cursor.moveToFirst()) {
- int domainCol = cursor.getColumnIndex(COOKIES_DOMAIN_COL);
- int pathCol = cursor.getColumnIndex(COOKIES_PATH_COL);
- int nameCol = cursor.getColumnIndex(COOKIES_NAME_COL);
- int valueCol = cursor.getColumnIndex(COOKIES_VALUE_COL);
- int expiresCol = cursor.getColumnIndex(COOKIES_EXPIRES_COL);
- int secureCol = cursor.getColumnIndex(COOKIES_SECURE_COL);
- do {
- Cookie cookie = new Cookie();
- cookie.domain = cursor.getString(domainCol);
- cookie.path = cursor.getString(pathCol);
- cookie.name = cursor.getString(nameCol);
- cookie.value = cursor.getString(valueCol);
- if (cursor.isNull(expiresCol)) {
- cookie.expires = -1;
- } else {
- cookie.expires = cursor.getLong(expiresCol);
- }
- cookie.secure = cursor.getShort(secureCol) != 0;
- cookie.mode = Cookie.MODE_NORMAL;
- list.add(cookie);
- } while (cursor.moveToNext());
+ Cursor cursor = null;
+ try {
+ cursor = mDatabase.query(mTableNames[TABLE_COOKIES_ID],
+ columns, selection, new String[] { domain }, null, null,
+ null);
+ if (cursor.moveToFirst()) {
+ int domainCol = cursor.getColumnIndex(COOKIES_DOMAIN_COL);
+ int pathCol = cursor.getColumnIndex(COOKIES_PATH_COL);
+ int nameCol = cursor.getColumnIndex(COOKIES_NAME_COL);
+ int valueCol = cursor.getColumnIndex(COOKIES_VALUE_COL);
+ int expiresCol = cursor.getColumnIndex(COOKIES_EXPIRES_COL);
+ int secureCol = cursor.getColumnIndex(COOKIES_SECURE_COL);
+ do {
+ Cookie cookie = new Cookie();
+ cookie.domain = cursor.getString(domainCol);
+ cookie.path = cursor.getString(pathCol);
+ cookie.name = cursor.getString(nameCol);
+ cookie.value = cursor.getString(valueCol);
+ if (cursor.isNull(expiresCol)) {
+ cookie.expires = -1;
+ } else {
+ cookie.expires = cursor.getLong(expiresCol);
+ }
+ cookie.secure = cursor.getShort(secureCol) != 0;
+ cookie.mode = Cookie.MODE_NORMAL;
+ list.add(cookie);
+ } while (cursor.moveToNext());
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getCookiesForDomain", e);
+ } finally {
+ if (cursor != null) cursor.close();
}
- cursor.close();
return list;
}
}
@@ -604,12 +617,12 @@
return null;
}
- Cursor cursor = mCacheDatabase.rawQuery("SELECT filepath, lastmodify, etag, expires, "
- + "expiresstring, mimetype, encoding, httpstatus, location, contentlength, "
- + "contentdisposition FROM cache WHERE url = ?",
- new String[] { url });
-
+ Cursor cursor = null;
+ final String query = "SELECT filepath, lastmodify, etag, expires, "
+ + "expiresstring, mimetype, encoding, httpstatus, location, contentlength, "
+ + "contentdisposition FROM cache WHERE url = ?";
try {
+ cursor = mCacheDatabase.rawQuery(query, new String[] { url });
if (cursor.moveToFirst()) {
CacheResult ret = new CacheResult();
ret.localPath = cursor.getString(0);
@@ -625,6 +638,8 @@
ret.contentdisposition = cursor.getString(10);
return ret;
}
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getCache", e);
} finally {
if (cursor != null) cursor.close();
}
@@ -688,78 +703,108 @@
return false;
}
- Cursor cursor = mCacheDatabase.query("cache", ID_PROJECTION,
- null, null, null, null, null);
- boolean ret = cursor.moveToFirst() == true;
- cursor.close();
+ Cursor cursor = null;
+ boolean ret = false;
+ try {
+ cursor = mCacheDatabase.query("cache", ID_PROJECTION,
+ null, null, null, null, null);
+ ret = cursor.moveToFirst() == true;
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "hasCache", e);
+ } finally {
+ if (cursor != null) cursor.close();
+ }
return ret;
}
long getCacheTotalSize() {
long size = 0;
- Cursor cursor = mCacheDatabase.rawQuery(
- "SELECT SUM(contentlength) as sum FROM cache", null);
- if (cursor.moveToFirst()) {
- size = cursor.getLong(0);
+ Cursor cursor = null;
+ final String query = "SELECT SUM(contentlength) as sum FROM cache";
+ try {
+ cursor = mCacheDatabase.rawQuery(query, null);
+ if (cursor.moveToFirst()) {
+ size = cursor.getLong(0);
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getCacheTotalSize", e);
+ } finally {
+ if (cursor != null) cursor.close();
}
- cursor.close();
return size;
}
List<String> trimCache(long amount) {
ArrayList<String> pathList = new ArrayList<String>(100);
- Cursor cursor = mCacheDatabase.rawQuery(
- "SELECT contentlength, filepath FROM cache ORDER BY expires ASC",
- null);
- if (cursor.moveToFirst()) {
- int batchSize = 100;
- StringBuilder pathStr = new StringBuilder(20 + 16 * batchSize);
- pathStr.append("DELETE FROM cache WHERE filepath IN (?");
- for (int i = 1; i < batchSize; i++) {
- pathStr.append(", ?");
- }
- pathStr.append(")");
- SQLiteStatement statement = mCacheDatabase.compileStatement(pathStr
- .toString());
- // as bindString() uses 1-based index, initialize index to 1
- int index = 1;
- do {
- long length = cursor.getLong(0);
- if (length == 0) {
- continue;
+ Cursor cursor = null;
+ final String query = "SELECT contentlength, filepath FROM cache ORDER BY expires ASC";
+ try {
+ cursor = mCacheDatabase.rawQuery(query, null);
+ if (cursor.moveToFirst()) {
+ int batchSize = 100;
+ StringBuilder pathStr = new StringBuilder(20 + 16 * batchSize);
+ pathStr.append("DELETE FROM cache WHERE filepath IN (?");
+ for (int i = 1; i < batchSize; i++) {
+ pathStr.append(", ?");
}
- amount -= length;
- String filePath = cursor.getString(1);
- statement.bindString(index, filePath);
- pathList.add(filePath);
- if (index++ == batchSize) {
- statement.execute();
- statement.clearBindings();
- index = 1;
+ pathStr.append(")");
+ SQLiteStatement statement = null;
+ try {
+ statement = mCacheDatabase.compileStatement(
+ pathStr.toString());
+ // as bindString() uses 1-based index, initialize index to 1
+ int index = 1;
+ do {
+ long length = cursor.getLong(0);
+ if (length == 0) {
+ continue;
+ }
+ amount -= length;
+ String filePath = cursor.getString(1);
+ statement.bindString(index, filePath);
+ pathList.add(filePath);
+ if (index++ == batchSize) {
+ statement.execute();
+ statement.clearBindings();
+ index = 1;
+ }
+ } while (cursor.moveToNext() && amount > 0);
+ if (index > 1) {
+ // there may be old bindings from the previous statement
+ // if index is less than batchSize, which is Ok.
+ statement.execute();
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "trimCache SQLiteStatement", e);
+ } finally {
+ if (statement != null) statement.close();
}
- } while (cursor.moveToNext() && amount > 0);
- if (index > 1) {
- // there may be old bindings from the previous statement if
- // index is less than batchSize, which is Ok.
- statement.execute();
}
- statement.close();
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "trimCache Cursor", e);
+ } finally {
+ if (cursor != null) cursor.close();
}
- cursor.close();
return pathList;
}
List<String> getAllCacheFileNames() {
ArrayList<String> pathList = null;
- Cursor cursor = mCacheDatabase.rawQuery("SELECT filepath FROM cache",
- null);
- if (cursor != null && cursor.moveToFirst()) {
- pathList = new ArrayList<String>(cursor.getCount());
- do {
- pathList.add(cursor.getString(0));
- } while (cursor.moveToNext());
+ Cursor cursor = null;
+ try {
+ cursor = mCacheDatabase.rawQuery("SELECT filepath FROM cache",
+ null);
+ if (cursor != null && cursor.moveToFirst()) {
+ pathList = new ArrayList<String>(cursor.getCount());
+ do {
+ pathList.add(cursor.getString(0));
+ } while (cursor.moveToNext());
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getAllCacheFileNames", e);
+ } finally {
+ if (cursor != null) cursor.close();
}
- cursor.close();
return pathList;
}
@@ -809,17 +854,23 @@
final String selection = "(" + PASSWORD_HOST_COL + " == ?)";
synchronized (mPasswordLock) {
String[] ret = null;
- Cursor cursor = mDatabase.query(mTableNames[TABLE_PASSWORD_ID],
- columns, selection, new String[] { schemePlusHost }, null,
- null, null);
- if (cursor.moveToFirst()) {
- ret = new String[2];
- ret[0] = cursor.getString(
- cursor.getColumnIndex(PASSWORD_USERNAME_COL));
- ret[1] = cursor.getString(
- cursor.getColumnIndex(PASSWORD_PASSWORD_COL));
+ Cursor cursor = null;
+ try {
+ cursor = mDatabase.query(mTableNames[TABLE_PASSWORD_ID],
+ columns, selection, new String[] { schemePlusHost }, null,
+ null, null);
+ if (cursor.moveToFirst()) {
+ ret = new String[2];
+ ret[0] = cursor.getString(
+ cursor.getColumnIndex(PASSWORD_USERNAME_COL));
+ ret[1] = cursor.getString(
+ cursor.getColumnIndex(PASSWORD_PASSWORD_COL));
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getUsernamePassword", e);
+ } finally {
+ if (cursor != null) cursor.close();
}
- cursor.close();
return ret;
}
}
@@ -900,17 +951,23 @@
+ HTTPAUTH_REALM_COL + " == ?)";
synchronized (mHttpAuthLock) {
String[] ret = null;
- Cursor cursor = mDatabase.query(mTableNames[TABLE_HTTPAUTH_ID],
- columns, selection, new String[] { host, realm }, null,
- null, null);
- if (cursor.moveToFirst()) {
- ret = new String[2];
- ret[0] = cursor.getString(
- cursor.getColumnIndex(HTTPAUTH_USERNAME_COL));
- ret[1] = cursor.getString(
- cursor.getColumnIndex(HTTPAUTH_PASSWORD_COL));
+ Cursor cursor = null;
+ try {
+ cursor = mDatabase.query(mTableNames[TABLE_HTTPAUTH_ID],
+ columns, selection, new String[] { host, realm }, null,
+ null, null);
+ if (cursor.moveToFirst()) {
+ ret = new String[2];
+ ret[0] = cursor.getString(
+ cursor.getColumnIndex(HTTPAUTH_USERNAME_COL));
+ ret[1] = cursor.getString(
+ cursor.getColumnIndex(HTTPAUTH_PASSWORD_COL));
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getHttpAuthUsernamePassword", e);
+ } finally {
+ if (cursor != null) cursor.close();
}
- cursor.close();
return ret;
}
}
@@ -958,18 +1015,24 @@
final String selection = "(" + FORMURL_URL_COL + " == ?)";
synchronized (mFormLock) {
long urlid = -1;
- Cursor cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
- ID_PROJECTION, selection, new String[] { url }, null, null,
- null);
- if (cursor.moveToFirst()) {
- urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
- } else {
- ContentValues c = new ContentValues();
- c.put(FORMURL_URL_COL, url);
- urlid = mDatabase.insert(
- mTableNames[TABLE_FORMURL_ID], null, c);
+ Cursor cursor = null;
+ try {
+ cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
+ ID_PROJECTION, selection, new String[] { url }, null, null,
+ null);
+ if (cursor.moveToFirst()) {
+ urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
+ } else {
+ ContentValues c = new ContentValues();
+ c.put(FORMURL_URL_COL, url);
+ urlid = mDatabase.insert(
+ mTableNames[TABLE_FORMURL_ID], null, c);
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "setFormData", e);
+ } finally {
+ if (cursor != null) cursor.close();
}
- cursor.close();
if (urlid >= 0) {
Set<Entry<String, String>> set = formdata.entrySet();
Iterator<Entry<String, String>> iter = set.iterator();
@@ -1002,27 +1065,39 @@
final String dataSelection = "(" + FORMDATA_URLID_COL + " == ?) AND ("
+ FORMDATA_NAME_COL + " == ?)";
synchronized (mFormLock) {
- Cursor cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
- ID_PROJECTION, urlSelection, new String[] { url }, null,
- null, null);
- if (cursor.moveToFirst()) {
- long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
- Cursor dataCursor = mDatabase.query(
- mTableNames[TABLE_FORMDATA_ID],
- new String[] { ID_COL, FORMDATA_VALUE_COL },
- dataSelection,
- new String[] { Long.toString(urlid), name }, null,
+ Cursor cursor = null;
+ try {
+ cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
+ ID_PROJECTION, urlSelection, new String[] { url }, null,
null, null);
- if (dataCursor.moveToFirst()) {
- int valueCol =
- dataCursor.getColumnIndex(FORMDATA_VALUE_COL);
- do {
- values.add(dataCursor.getString(valueCol));
- } while (dataCursor.moveToNext());
+ if (cursor.moveToFirst()) {
+ long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
+ Cursor dataCursor = null;
+ try {
+ dataCursor = mDatabase.query(
+ mTableNames[TABLE_FORMDATA_ID],
+ new String[] { ID_COL, FORMDATA_VALUE_COL },
+ dataSelection,
+ new String[] { Long.toString(urlid), name },
+ null, null, null);
+ if (dataCursor.moveToFirst()) {
+ int valueCol = dataCursor.getColumnIndex(
+ FORMDATA_VALUE_COL);
+ do {
+ values.add(dataCursor.getString(valueCol));
+ } while (dataCursor.moveToNext());
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getFormData dataCursor", e);
+ } finally {
+ if (dataCursor != null) dataCursor.close();
+ }
}
- dataCursor.close();
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getFormData cursor", e);
+ } finally {
+ if (cursor != null) cursor.close();
}
- cursor.close();
return values;
}
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 86011d7..a30059c 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1835,9 +1835,11 @@
mSelectedPosition < mAdapter.getCount()) {
final View view = getChildAt(mSelectedPosition - mFirstPosition);
- performItemClick(view, mSelectedPosition, mSelectedRowId);
+ if (view != null) {
+ performItemClick(view, mSelectedPosition, mSelectedRowId);
+ view.setPressed(false);
+ }
setPressed(false);
- if (view != null) view.setPressed(false);
return true;
}
break;
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 3328c13..52a560c 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -216,23 +216,23 @@
}
/**
- * Sets the drawable to use as the left part of the strip below the
+ * Sets the drawable to use as the right part of the strip below the
* tab indicators.
- * @param drawable the left strip drawable
+ * @param drawable the right strip drawable
*/
public void setRightStripDrawable(Drawable drawable) {
- mBottomLeftStrip = drawable;
+ mBottomRightStrip = drawable;
requestLayout();
invalidate(); }
/**
- * Sets the drawable to use as the left part of the strip below the
+ * Sets the drawable to use as the right part of the strip below the
* tab indicators.
* @param resId the resource identifier of the drawable to use as the
- * left strip drawable
+ * right strip drawable
*/
public void setRightStripDrawable(int resId) {
- mBottomLeftStrip = mContext.getResources().getDrawable(resId);
+ mBottomRightStrip = mContext.getResources().getDrawable(resId);
requestLayout();
invalidate();
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 9b7f487..37cd412 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -89,7 +89,7 @@
public static final int MODE_UNSPECIFIED = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
public static final int MODE_PATTERN = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
public static final int MODE_PIN = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
- public static final int MODE_PASSWORD = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+ public static final int MODE_PASSWORD = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
/**
* The minimum number of dots the user must include in a wrong pattern
@@ -144,12 +144,11 @@
/**
* Gets the device policy password mode. If the mode is non-specific, returns
* MODE_PATTERN which allows the user to choose anything.
- *
- * @return
*/
public int getRequestedPasswordMode() {
int policyMode = getDevicePolicyManager().getPasswordQuality(null);
switch (policyMode) {
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
return MODE_PASSWORD;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
@@ -270,9 +269,41 @@
}
/**
+ * Used by device policy manager to validate the current password
+ * information it has.
+ */
+ public int getActivePasswordQuality() {
+ switch (getPasswordMode()) {
+ case MODE_UNSPECIFIED:
+ return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ case MODE_PATTERN:
+ if (isLockPatternEnabled()) {
+ return DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+ } else {
+ return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ }
+ case MODE_PIN:
+ if (isLockPasswordEnabled()) {
+ return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+ } else {
+ return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ }
+ case MODE_PASSWORD:
+ if (isLockPasswordEnabled()) {
+ return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+ } else {
+ return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ }
+ }
+ return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ }
+
+ /**
* Clear any lock pattern or password.
*/
public void clearLock() {
+ getDevicePolicyManager().setActivePasswordState(
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
saveLockPassword(null, LockPatternUtils.MODE_PATTERN);
setLockPatternEnabled(false);
saveLockPattern(null);
@@ -316,15 +347,9 @@
}
/**
- * Compare the given password and mode, ensuring that the password meets
- * the mode and returning the minimum mode needed for the given password.
- * @param password The password to be used.
- * @param reqMode The desired password mode.
- * @return Returns {@link #MODE_UNSPECIFIED} if the password is not
- * good enough for the given mode. Otherwise, returns either the original
- * reqMode or something better if that is needed for the given password.
+ * Compute the password quality from the given password string.
*/
- static public int adjustPasswordMode(String password, int reqMode) {
+ static public int computePasswordQuality(String password) {
boolean hasDigit = false;
boolean hasNonDigit = false;
final int len = password.length();
@@ -336,39 +361,16 @@
}
}
- // First check if it is sufficient.
- switch (reqMode) {
- case MODE_PASSWORD: {
- if (!hasDigit || !hasNonDigit) {
- return MODE_UNSPECIFIED;
- }
- } break;
-
- case MODE_PIN:
- case MODE_PATTERN: {
- // Whatever we have is acceptable; we may need to promote the
- // mode later.
- } break;
-
- default:
- // If it isn't a mode we specifically know, then fail fast.
- Log.w(TAG, "adjustPasswordMode: unknown mode " + reqMode);
- return MODE_UNSPECIFIED;
+ if (hasNonDigit && hasDigit) {
+ return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
}
-
- // Do we need to promote?
if (hasNonDigit) {
- if (reqMode < MODE_PASSWORD) {
- reqMode = MODE_PASSWORD;
- }
+ return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
}
if (hasDigit) {
- if (reqMode < MODE_PIN) {
- reqMode = MODE_PIN;
- }
+ return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
}
-
- return reqMode;
+ return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
}
/**
@@ -392,12 +394,15 @@
raf.close();
DevicePolicyManager dpm = getDevicePolicyManager();
if (password != null) {
- int finalMode = adjustPasswordMode(password, mode);
- if (mode < finalMode) {
- mode = finalMode;
- }
setLong(PASSWORD_TYPE_KEY, mode);
- dpm.setActivePasswordState(mode, password.length());
+ int quality = computePasswordQuality(password);
+ if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ dpm.setActivePasswordState(quality, password.length());
+ } else {
+ // The password is not anything.
+ dpm.setActivePasswordState(
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
+ }
} else {
dpm.setActivePasswordState(
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/core/java/com/google/android/mms/pdu/PduPersister.java
index 2a1f23a..d4ac24a 100644
--- a/core/java/com/google/android/mms/pdu/PduPersister.java
+++ b/core/java/com/google/android/mms/pdu/PduPersister.java
@@ -424,7 +424,8 @@
// faster.
if ("text/plain".equals(type) || "application/smil".equals(type)) {
String text = c.getString(PART_COLUMN_TEXT);
- byte [] blob = new EncodedStringValue(text).getTextString();
+ byte [] blob = new EncodedStringValue(text != null ? text : "")
+ .getTextString();
baos.write(blob, 0, blob.length);
} else {
@@ -858,7 +859,7 @@
} else {
values.put(Mms.SUBJECT, "");
}
-
+
long messageSize = sendReq.getMessageSize();
if (messageSize > 0) {
values.put(Mms.MESSAGE_SIZE, messageSize);
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 5432efb..0e7fd66 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -564,7 +564,10 @@
NULL, NULL, NULL, NULL, NULL);
tearDownEventLoop(nat);
nat->vm->DetachCurrentThread();
- shutdown(nat->controlFdR,SHUT_RDWR);
+
+ int fd = nat->controlFdR;
+ nat->controlFdR = 0;
+ close(fd);
return NULL;
}
case EVENT_LOOP_ADD:
@@ -653,9 +656,12 @@
done:
if (JNI_FALSE == result) {
- if (nat->controlFdW || nat->controlFdR) {
- shutdown(nat->controlFdW, SHUT_RDWR);
+ if (nat->controlFdW) {
+ close(nat->controlFdW);
nat->controlFdW = 0;
+ }
+ if (nat->controlFdR) {
+ close(nat->controlFdR);
nat->controlFdR = 0;
}
if (nat->me) env->DeleteGlobalRef(nat->me);
@@ -692,9 +698,10 @@
nat->watchData = NULL;
nat->pollDataSize = 0;
nat->pollMemberCount = 0;
- shutdown(nat->controlFdW, SHUT_RDWR);
+
+ int fd = nat->controlFdW;
nat->controlFdW = 0;
- nat->controlFdR = 0;
+ close(fd);
}
pthread_mutex_unlock(&(nat->thread_mutex));
#endif // HAVE_BLUETOOTH
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4e2caa0..a3c73d8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -732,7 +732,7 @@
@hide -->
<permission android:name="android.permission.ASEC_ACCESS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="dangerous"
+ android:protectionLevel="signature"
android:label="@string/permlab_asec_access"
android:description="@string/permdesc_asec_access" />
@@ -740,7 +740,7 @@
@hide -->
<permission android:name="android.permission.ASEC_CREATE"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="dangerous"
+ android:protectionLevel="signature"
android:label="@string/permlab_asec_create"
android:description="@string/permdesc_asec_create" />
@@ -748,7 +748,7 @@
@hide -->
<permission android:name="android.permission.ASEC_DESTROY"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="dangerous"
+ android:protectionLevel="signature"
android:label="@string/permlab_asec_destroy"
android:description="@string/permdesc_asec_destroy" />
@@ -756,7 +756,7 @@
@hide -->
<permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="dangerous"
+ android:protectionLevel="signature"
android:label="@string/permlab_asec_mount_unmount"
android:description="@string/permdesc_asec_mount_unmount" />
@@ -764,7 +764,7 @@
@hide -->
<permission android:name="android.permission.ASEC_RENAME"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="dangerous"
+ android:protectionLevel="signature"
android:label="@string/permlab_asec_rename"
android:description="@string/permdesc_asec_rename" />
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index ad71fcb..095ee13 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -574,5 +574,13 @@
.appendQueryParameter("key", "y z")
.build();
assertEquals("y z", uri.getQueryParameter("key"));
+
+ // key is a substring of parameters, but not present
+ uri = Uri.parse("http://test/").buildUpon()
+ .appendQueryParameter("akeyb", "a b")
+ .appendQueryParameter("keya", "c d")
+ .appendQueryParameter("bkey", "e f")
+ .build();
+ assertNull(uri.getQueryParameter("key"));
}
}
diff --git a/data/fonts/DroidSansHebrew.ttf b/data/fonts/DroidSansHebrew.ttf
index 8cc670d..0b48628 100644
--- a/data/fonts/DroidSansHebrew.ttf
+++ b/data/fonts/DroidSansHebrew.ttf
Binary files differ
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 44a5a6b..8dc206c 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -35,8 +35,12 @@
import android.net.NetworkInfo;
import android.net.SntpClient;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -65,13 +69,13 @@
*
* {@hide}
*/
-public class GpsLocationProvider implements LocationProviderInterface {
+public class GpsLocationProvider implements LocationProviderInterface, Runnable {
private static final String TAG = "GpsLocationProvider";
private static final boolean DEBUG = false;
private static final boolean VERBOSE = false;
-
+
/**
* Broadcast intent action indicating that the GPS has either been
* enabled or disabled. An intent extra provides this state as a boolean,
@@ -155,6 +159,17 @@
private static final int AGPS_DATA_CONNECTION_OPENING = 1;
private static final int AGPS_DATA_CONNECTION_OPEN = 2;
+ // Handler messages
+ private static final int CHECK_LOCATION = 1;
+ private static final int ENABLE = 2;
+ private static final int ENABLE_TRACKING = 3;
+ private static final int UPDATE_NETWORK_STATE = 4;
+ private static final int INJECT_NTP_TIME = 5;
+ private static final int DOWNLOAD_XTRA_DATA = 6;
+ private static final int UPDATE_LOCATION = 7;
+ private static final int ADD_LISTENER = 8;
+ private static final int REMOVE_LISTENER = 9;
+
private static final String PROPERTIES_FILE = "/etc/gps.conf";
private int mLocationFlags = LOCATION_INVALID;
@@ -180,6 +195,11 @@
// true if we have network connectivity
private boolean mNetworkAvailable;
+ // flags to trigger NTP or XTRA data download when network becomes available
+ // initialized to true so we do NTP and XTRA when the network comes up after booting
+ private boolean mInjectNtpTimePending = true;
+ private boolean mDownloadXtraDataPending = true;
+
// true if GPS is navigating
private boolean mNavigating;
@@ -215,9 +235,9 @@
private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
private Bundle mLocationExtras = new Bundle();
private ArrayList<Listener> mListeners = new ArrayList<Listener>();
- private GpsEventThread mEventThread;
- private GpsNetworkThread mNetworkThread;
- private Object mNetworkThreadLock = new Object();
+
+ private Handler mHandler;
+ private Thread mEventThread;
private String mAGpsApn;
private int mAGpsDataConnectionState;
@@ -333,11 +353,6 @@
mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ALARM_WAKEUP);
- intentFilter.addAction(ALARM_TIMEOUT);
- context.registerReceiver(mBroadcastReciever, intentFilter);
-
mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
// Battery statistics service to be notified when GPS turns on or off
@@ -373,6 +388,17 @@
} catch (IOException e) {
Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
}
+
+ Thread thread = new Thread(null, this, "GpsLocationProvider");
+ thread.start();
+ }
+
+ private void initialize() {
+ // register our receiver on our thread rather than the main thread
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ALARM_WAKEUP);
+ intentFilter.addAction(ALARM_TIMEOUT);
+ mContext.registerReceiver(mBroadcastReciever, intentFilter);
}
/**
@@ -391,6 +417,14 @@
}
public void updateNetworkState(int state, NetworkInfo info) {
+ mHandler.removeMessages(UPDATE_NETWORK_STATE);
+ Message m = Message.obtain(mHandler, UPDATE_NETWORK_STATE);
+ m.arg1 = state;
+ m.obj = info;
+ mHandler.sendMessage(m);
+ }
+
+ private void handleUpdateNetworkState(int state, NetworkInfo info) {
mNetworkAvailable = (state == LocationProvider.AVAILABLE);
if (DEBUG) {
@@ -414,10 +448,84 @@
}
}
- if (mNetworkAvailable && mNetworkThread != null && mEnabled) {
- // signal the network thread when the network becomes available
- mNetworkThread.signal();
- }
+ if (mNetworkAvailable) {
+ if (mInjectNtpTimePending) {
+ mHandler.removeMessages(INJECT_NTP_TIME);
+ mHandler.sendMessage(Message.obtain(mHandler, INJECT_NTP_TIME));
+ }
+ if (mDownloadXtraDataPending) {
+ mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
+ mHandler.sendMessage(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA));
+ }
+ }
+ }
+
+ private void handleInjectNtpTime() {
+ if (!mNetworkAvailable) {
+ // try again when network is up
+ mInjectNtpTimePending = true;
+ return;
+ }
+ mInjectNtpTimePending = false;
+
+ SntpClient client = new SntpClient();
+ long delay;
+
+ if (client.requestTime(mNtpServer, 10000)) {
+ long time = client.getNtpTime();
+ long timeReference = client.getNtpTimeReference();
+ int certainty = (int)(client.getRoundTripTime()/2);
+ long now = System.currentTimeMillis();
+ long systemTimeOffset = time - now;
+
+ Log.d(TAG, "NTP server returned: "
+ + time + " (" + new Date(time)
+ + ") reference: " + timeReference
+ + " certainty: " + certainty
+ + " system time offset: " + systemTimeOffset);
+
+ // sanity check NTP time and do not use if it is too far from system time
+ if (systemTimeOffset < 0) {
+ systemTimeOffset = -systemTimeOffset;
+ }
+ if (systemTimeOffset < MAX_NTP_SYSTEM_TIME_OFFSET) {
+ native_inject_time(time, timeReference, certainty);
+ } else {
+ Log.e(TAG, "NTP time differs from system time by " + systemTimeOffset
+ + "ms. Ignoring.");
+ }
+ delay = NTP_INTERVAL;
+ } else {
+ if (DEBUG) Log.d(TAG, "requestTime failed");
+ delay = RETRY_INTERVAL;
+ }
+
+ // send delayed message for next NTP injection
+ mHandler.removeMessages(INJECT_NTP_TIME);
+ mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
+ }
+
+ private void handleDownloadXtraData() {
+ if (!mDownloadXtraDataPending) {
+ // try again when network is up
+ mDownloadXtraDataPending = true;
+ return;
+ }
+ mDownloadXtraDataPending = false;
+
+
+ GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
+ byte[] data = xtraDownloader.downloadXtraData();
+ if (data != null) {
+ if (DEBUG) {
+ Log.d(TAG, "calling native_inject_xtra_data");
+ }
+ native_inject_xtra_data(data, data.length);
+ } else {
+ // try again later
+ mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
+ mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
+ }
}
/**
@@ -425,6 +533,13 @@
* Someday we might use this for network location injection to aid the GPS
*/
public void updateLocation(Location location) {
+ mHandler.removeMessages(UPDATE_LOCATION);
+ Message m = Message.obtain(mHandler, UPDATE_LOCATION);
+ m.obj = location;
+ mHandler.sendMessage(m);
+ }
+
+ private void handleUpdateLocation(Location location) {
if (location.hasAccuracy()) {
native_inject_location(location.getLatitude(), location.getLongitude(),
location.getAccuracy());
@@ -513,8 +628,17 @@
* must be handled. Hardware may be started up
* when the provider is enabled.
*/
- public synchronized void enable() {
- if (DEBUG) Log.d(TAG, "enable");
+ public void enable() {
+ synchronized (mHandler) {
+ mHandler.removeMessages(ENABLE);
+ Message m = Message.obtain(mHandler, ENABLE);
+ m.arg1 = 1;
+ mHandler.sendMessage(m);
+ }
+ }
+
+ private void handleEnable() {
+ if (DEBUG) Log.d(TAG, "handleEnable");
if (mEnabled) return;
mEnabled = native_init();
@@ -529,16 +653,6 @@
// run event listener thread while we are enabled
mEventThread = new GpsEventThread();
mEventThread.start();
-
- if (requiresNetwork()) {
- // run network thread for NTP and XTRA support
- if (mNetworkThread == null) {
- mNetworkThread = new GpsNetworkThread();
- mNetworkThread.start();
- } else {
- mNetworkThread.signal();
- }
- }
} else {
Log.w(TAG, "Failed to enable location provider");
}
@@ -549,8 +663,17 @@
* need not be handled. Hardware may be shut
* down while the provider is disabled.
*/
- public synchronized void disable() {
- if (DEBUG) Log.d(TAG, "disable");
+ public void disable() {
+ synchronized (mHandler) {
+ mHandler.removeMessages(ENABLE);
+ Message m = Message.obtain(mHandler, ENABLE);
+ m.arg1 = 0;
+ mHandler.sendMessage(m);
+ }
+ }
+
+ private void handleDisable() {
+ if (DEBUG) Log.d(TAG, "handleEnable");
if (!mEnabled) return;
mEnabled = false;
@@ -567,11 +690,6 @@
mEventThread = null;
}
- if (mNetworkThread != null) {
- mNetworkThread.setDone();
- mNetworkThread = null;
- }
-
// do this before releasing wakelock
native_cleanup();
@@ -610,6 +728,15 @@
}
public void enableLocationTracking(boolean enable) {
+ synchronized (mHandler) {
+ mHandler.removeMessages(ENABLE_TRACKING);
+ Message m = Message.obtain(mHandler, ENABLE_TRACKING);
+ m.arg1 = (enable ? 1 : 0);
+ mHandler.sendMessage(m);
+ }
+ }
+
+ private void handleEnableLocationTracking(boolean enable) {
if (enable) {
mTTFF = 0;
mLastFixTime = 0;
@@ -659,6 +786,12 @@
}
public void addListener(int uid) {
+ Message m = Message.obtain(mHandler, ADD_LISTENER);
+ m.arg1 = uid;
+ mHandler.sendMessage(m);
+ }
+
+ private void handleAddListener(int uid) {
synchronized(mListeners) {
if (mClientUids.indexOfKey(uid) >= 0) {
// Shouldn't be here -- already have this uid.
@@ -677,6 +810,12 @@
}
public void removeListener(int uid) {
+ Message m = Message.obtain(mHandler, REMOVE_LISTENER);
+ m.arg1 = uid;
+ mHandler.sendMessage(m);
+ }
+
+ private void handleRemoveListener(int uid) {
synchronized(mListeners) {
if (mClientUids.indexOfKey(uid) < 0) {
// Shouldn't be here -- don't have this uid.
@@ -700,10 +839,12 @@
return deleteAidingData(extras);
}
if ("force_time_injection".equals(command)) {
- return forceTimeInjection();
+ mHandler.removeMessages(INJECT_NTP_TIME);
+ mHandler.sendMessage(Message.obtain(mHandler, INJECT_NTP_TIME));
+ return true;
}
if ("force_xtra_injection".equals(command)) {
- if (native_supports_xtra() && mNetworkThread != null) {
+ if (native_supports_xtra()) {
xtraDownloadRequest();
return true;
}
@@ -744,16 +885,7 @@
return false;
}
- private boolean forceTimeInjection() {
- if (DEBUG) Log.d(TAG, "forceTimeInjection");
- if (mNetworkThread != null) {
- mNetworkThread.timeInjectRequest();
- return true;
- }
- return false;
- }
-
- public void startNavigating() {
+ private void startNavigating() {
if (!mStarted) {
if (DEBUG) Log.d(TAG, "startNavigating");
mStarted = true;
@@ -784,7 +916,7 @@
}
}
- public void stopNavigating() {
+ private void stopNavigating() {
if (DEBUG) Log.d(TAG, "stopNavigating");
if (mStarted) {
mStarted = false;
@@ -1092,11 +1224,13 @@
}
}
+ /**
+ * called from native code to request XTRA data
+ */
private void xtraDownloadRequest() {
if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
- if (mNetworkThread != null) {
- mNetworkThread.xtraDownloadRequest();
- }
+ mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
+ mHandler.sendMessage(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA));
}
//=============================================================
@@ -1189,6 +1323,10 @@
mNIHandler.handleNiNotification(notification);
}
+ // this thread is used to receive events from the native code.
+ // native_wait_for_event() will callback to us via reportLocation(), reportStatus(), etc.
+ // this is necessary because native code cannot call Java on a thread that the JVM does
+ // not know about.
private class GpsEventThread extends Thread {
public GpsEventThread() {
@@ -1207,157 +1345,52 @@
}
}
- private class GpsNetworkThread extends Thread {
-
- private long mNextNtpTime = 0;
- private long mNextXtraTime = 0;
- private boolean mTimeInjectRequested = false;
- private boolean mXtraDownloadRequested = false;
- private boolean mDone = false;
-
- public GpsNetworkThread() {
- super("GpsNetworkThread");
- }
-
- public void run() {
- synchronized (mNetworkThreadLock) {
- if (!mDone) {
- runLocked();
- }
- }
- }
-
- public void runLocked() {
- if (DEBUG) Log.d(TAG, "NetworkThread starting");
-
- SntpClient client = new SntpClient();
- GpsXtraDownloader xtraDownloader = null;
-
- if (native_supports_xtra()) {
- xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
- }
-
- // thread exits after disable() is called
- while (!mDone) {
- long waitTime = getWaitTime();
- do {
- synchronized (this) {
- try {
- if (!mNetworkAvailable) {
- if (DEBUG) Log.d(TAG, "NetworkThread wait for network");
- wait();
- } else if (waitTime > 0) {
- if (DEBUG) {
- Log.d(TAG, "NetworkThread wait for " +
- waitTime + "ms");
- }
- wait(waitTime);
- }
- } catch (InterruptedException e) {
- if (DEBUG) {
- Log.d(TAG, "InterruptedException in GpsNetworkThread");
- }
- }
+ private final class ProviderHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg)
+ {
+ switch (msg.what) {
+ case ENABLE:
+ if (msg.arg1 == 1) {
+ handleEnable();
+ } else {
+ handleDisable();
}
- waitTime = getWaitTime();
- } while (!mDone && ((!mXtraDownloadRequested &&
- !mTimeInjectRequested && waitTime > 0)
- || !mNetworkAvailable));
- if (DEBUG) Log.d(TAG, "NetworkThread out of wake loop");
- if (!mDone) {
- if (mNtpServer != null &&
- (mTimeInjectRequested || mNextNtpTime <= System.currentTimeMillis())) {
- if (DEBUG) {
- Log.d(TAG, "Requesting time from NTP server " + mNtpServer);
- }
- mTimeInjectRequested = false;
- if (client.requestTime(mNtpServer, 10000)) {
- long time = client.getNtpTime();
- long timeReference = client.getNtpTimeReference();
- int certainty = (int)(client.getRoundTripTime()/2);
- long now = System.currentTimeMillis();
- long systemTimeOffset = time - now;
-
- Log.d(TAG, "NTP server returned: "
- + time + " (" + new Date(time)
- + ") reference: " + timeReference
- + " certainty: " + certainty
- + " system time offset: " + systemTimeOffset);
-
- // sanity check NTP time and do not use if it is too far from system time
- if (systemTimeOffset < 0) {
- systemTimeOffset = -systemTimeOffset;
- }
- if (systemTimeOffset < MAX_NTP_SYSTEM_TIME_OFFSET) {
- native_inject_time(time, timeReference, certainty);
- } else {
- Log.e(TAG, "NTP time differs from system time by " + systemTimeOffset
- + "ms. Ignoring.");
- }
- mNextNtpTime = now + NTP_INTERVAL;
- } else {
- if (DEBUG) Log.d(TAG, "requestTime failed");
- mNextNtpTime = System.currentTimeMillis() + RETRY_INTERVAL;
- }
+ break;
+ case ENABLE_TRACKING:
+ handleEnableLocationTracking(msg.arg1 == 1);
+ break;
+ case UPDATE_NETWORK_STATE:
+ handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
+ break;
+ case INJECT_NTP_TIME:
+ handleInjectNtpTime();
+ break;
+ case DOWNLOAD_XTRA_DATA:
+ if (native_supports_xtra()) {
+ handleDownloadXtraData();
}
-
- if ((mXtraDownloadRequested ||
- (mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis()))
- && xtraDownloader != null) {
- mXtraDownloadRequested = false;
- byte[] data = xtraDownloader.downloadXtraData();
- if (data != null) {
- if (DEBUG) {
- Log.d(TAG, "calling native_inject_xtra_data");
- }
- native_inject_xtra_data(data, data.length);
- mNextXtraTime = 0;
- } else {
- mNextXtraTime = System.currentTimeMillis() + RETRY_INTERVAL;
- }
- }
- }
+ break;
+ case UPDATE_LOCATION:
+ handleUpdateLocation((Location)msg.obj);
+ break;
+ case ADD_LISTENER:
+ handleAddListener(msg.arg1);
+ break;
+ case REMOVE_LISTENER:
+ handleRemoveListener(msg.arg1);
+ break;
}
- if (DEBUG) Log.d(TAG, "NetworkThread exiting");
}
-
- synchronized void xtraDownloadRequest() {
- mXtraDownloadRequested = true;
- notify();
- }
+ };
- synchronized void timeInjectRequest() {
- mTimeInjectRequested = true;
- notify();
- }
-
- synchronized void signal() {
- notify();
- }
-
- synchronized void setDone() {
- if (DEBUG) Log.d(TAG, "stopping NetworkThread");
- mDone = true;
- notify();
- }
-
- private long getWaitTime() {
- long now = System.currentTimeMillis();
- long waitTime = Long.MAX_VALUE;
- if (mNtpServer != null) {
- waitTime = mNextNtpTime - now;
- }
- if (mNextXtraTime != 0) {
- long xtraWaitTime = mNextXtraTime - now;
- if (xtraWaitTime < waitTime) {
- waitTime = xtraWaitTime;
- }
- }
- if (waitTime < 0) {
- waitTime = 0;
- }
- return waitTime;
- }
+ public void run()
+ {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ initialize();
+ Looper.prepare();
+ mHandler = new ProviderHandler();
+ Looper.loop();
}
// for GPS SV statistics
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 68b351b..b56e638 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1472,8 +1472,6 @@
//====================================================================
// Remote Control
/**
- * @hide
- * TODO unhide for SDK
* TODO document for SDK
* @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
* that will receive the media button intent. This broadcast receiver must be declared
@@ -1490,21 +1488,6 @@
}
/**
- * @hide
- * TODO unhide for SDK
- * TODO document for SDK
- * @param eventReceiverClass class of a {@link android.content.BroadcastReceiver} that will
- * receive the media button intent. This broadcast receiver must be declared in the
- * application manifest.
- */
- public void registerMediaButtonEventReceiver(Class<?> eventReceiverClass) {
- registerMediaButtonEventReceiver(new ComponentName(
- eventReceiverClass.getPackage().getName(), eventReceiverClass.getName()));
- }
-
- /**
- * @hide
- * TODO unhide for SDK
* TODO document for SDK
*/
public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) {
@@ -1517,16 +1500,6 @@
}
/**
- * @hide
- * TODO unhide for SDK
- * TODO document for SDK
- */
- public void unregisterMediaButtonEventReceiver(Class<?> eventReceiverClass) {
- unregisterMediaButtonEventReceiver(new ComponentName(
- eventReceiverClass.getPackage().getName(), eventReceiverClass.getName()));
- }
-
- /**
* @hide
* Reload audio settings. This method is called by Settings backup
* agent when audio settings are restored and causes the AudioService
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index ae0eccb..74e6157 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -208,6 +208,9 @@
/** @see System#MODE_RINGER_STREAMS_AFFECTED */
private int mRingerModeAffectedStreams;
+ // Streams currently muted by ringer mode
+ private int mRingerModeMutedStreams;
+
/** @see System#MUTE_STREAMS_AFFECTED */
private int mMuteAffectedStreams;
@@ -404,7 +407,7 @@
VolumeStreamState streamState = mStreamStates[STREAM_VOLUME_ALIAS[streamType]];
- final int oldIndex = streamState.mIndex;
+ final int oldIndex = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex;
boolean adjustVolume = true;
// If either the client forces allowing ringer modes for this adjustment,
@@ -416,30 +419,43 @@
adjustVolume = checkForRingerModeChange(oldIndex, direction);
}
- if (adjustVolume && streamState.adjustIndex(direction)) {
- // Post message to set system volume (it in turn will post a message
- // to persist). Do not change volume if stream is muted.
- if (streamState.muteCount() == 0) {
+ // If stream is muted, adjust last audible index only
+ int index;
+ if (streamState.muteCount() != 0) {
+ if (adjustVolume) {
+ streamState.adjustLastAudibleIndex(direction);
+ // Post a persist volume msg
+ sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, streamType,
+ SENDMSG_REPLACE, 0, 1, streamState, PERSIST_DELAY);
+ }
+ index = streamState.mLastAudibleIndex;
+ } else {
+ if (adjustVolume && streamState.adjustIndex(direction)) {
+ // Post message to set system volume (it in turn will post a message
+ // to persist). Do not change volume if stream is muted.
sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, STREAM_VOLUME_ALIAS[streamType], SENDMSG_NOOP, 0, 0,
streamState, 0);
}
+ index = streamState.mIndex;
}
-
// UI
mVolumePanel.postVolumeChanged(streamType, flags);
// Broadcast Intent
- sendVolumeUpdate(streamType, oldIndex, streamState.mIndex);
+ sendVolumeUpdate(streamType, oldIndex, index);
}
/** @see AudioManager#setStreamVolume(int, int, int) */
public void setStreamVolume(int streamType, int index, int flags) {
ensureValidStreamType(streamType);
+ VolumeStreamState streamState = mStreamStates[STREAM_VOLUME_ALIAS[streamType]];
- final int oldIndex = mStreamStates[STREAM_VOLUME_ALIAS[streamType]].mIndex;
+ final int oldIndex = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex;
index = rescaleIndex(index * 10, streamType, STREAM_VOLUME_ALIAS[streamType]);
setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true);
+ index = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex;
+
// UI, etc.
mVolumePanel.postVolumeChanged(streamType, flags);
// Broadcast Intent
@@ -470,22 +486,30 @@
*/
private void setStreamVolumeInt(int streamType, int index, boolean force, boolean lastAudible) {
VolumeStreamState streamState = mStreamStates[streamType];
- if (streamState.setIndex(index, lastAudible) || force) {
- // Post message to set system volume (it in turn will post a message
- // to persist).
- // If stream is muted or we are in silent mode and stream is affected by ringer mode
- // and the new volume is not 0, just persist the new volume but do not change
- // current value
- if (streamState.muteCount() == 0 &&
- (mRingerMode == AudioManager.RINGER_MODE_NORMAL ||
- !isStreamAffectedByRingerMode(streamType) ||
- index == 0)) {
- sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0,
- streamState, 0);
- } else {
- // Post a persist volume msg
- sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, streamType,
- SENDMSG_REPLACE, 0, 1, streamState, PERSIST_DELAY);
+
+ // If stream is muted, set last audible index only
+ if (streamState.muteCount() != 0) {
+ streamState.setLastAudibleIndex(index);
+ // Post a persist volume msg
+ sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, streamType,
+ SENDMSG_REPLACE, 0, 1, streamState, PERSIST_DELAY);
+ } else {
+ if (streamState.setIndex(index, lastAudible) || force) {
+ // Post message to set system volume (it in turn will post a message
+ // to persist).
+ // If we are in silent mode and stream is affected by ringer mode
+ // and the new volume is not 0, just persist the new volume but do not change
+ // current value
+ if (mRingerMode == AudioManager.RINGER_MODE_NORMAL ||
+ !isStreamAffectedByRingerMode(streamType) ||
+ index == 0) {
+ sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0,
+ streamState, 0);
+ } else {
+ // Post a persist volume msg
+ sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, streamType,
+ SENDMSG_REPLACE, 0, 1, streamState, PERSIST_DELAY);
+ }
}
}
}
@@ -537,27 +561,24 @@
private void setRingerModeInt(int ringerMode, boolean persist) {
mRingerMode = ringerMode;
- // Adjust volumes via posting message
+ // Mute stream if not previously muted by ringer mode and ringer mode
+ // is not RINGER_MODE_NORMAL and stream is affected by ringer mode.
+ // Unmute stream if previously muted by ringer mode and ringer mode
+ // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
int numStreamTypes = AudioSystem.getNumStreamTypes();
- if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
- for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
- if (!isStreamAffectedByRingerMode(streamType)) continue;
- // Bring back last audible volume
- setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex,
- true, false);
- }
- } else {
- for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
- if (isStreamAffectedByRingerMode(streamType)) {
- // Either silent or vibrate, either way volume is 0
- setStreamVolumeInt(streamType, 0, false, false);
- } else {
- // restore stream volume in the case the stream changed from affected
- // to non affected by ringer mode. Does not arm to do it for streams that
- // are not affected as well.
- setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex,
- true, false);
+ for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+ if (isStreamMutedByRingerMode(streamType)) {
+ if (!isStreamAffectedByRingerMode(streamType) ||
+ mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
+ mStreamStates[streamType].mute(null, false);
+ mRingerModeMutedStreams &= ~(1 << streamType);
}
+ } else {
+ if (isStreamAffectedByRingerMode(streamType) &&
+ mRingerMode != AudioManager.RINGER_MODE_NORMAL) {
+ mStreamStates[streamType].mute(null, true);
+ mRingerModeMutedStreams |= (1 << streamType);
+ }
}
}
@@ -728,7 +749,7 @@
}
int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
int index = mStreamStates[STREAM_VOLUME_ALIAS[streamType]].mIndex;
- setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, true, true);
+ setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, true, false);
}
}
@@ -862,7 +883,7 @@
}
streamState.mLastAudibleIndex = streamState.getValidIndex(index);
- // unmute stream that whas muted but is not affect by mute anymore
+ // unmute stream that was muted but is not affect by mute anymore
if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType)) {
int size = streamState.mDeathHandlers.size();
for (int i = 0; i < size; i++) {
@@ -1127,6 +1148,10 @@
return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
}
+ private boolean isStreamMutedByRingerMode(int streamType) {
+ return (mRingerModeMutedStreams & (1 << streamType)) != 0;
+ }
+
public boolean isStreamAffectedByMute(int streamType) {
return (mMuteAffectedStreams & (1 << streamType)) != 0;
}
@@ -1293,6 +1318,14 @@
}
}
+ public void setLastAudibleIndex(int index) {
+ mLastAudibleIndex = getValidIndex(index);
+ }
+
+ public void adjustLastAudibleIndex(int deltaIndex) {
+ setLastAudibleIndex(mLastAudibleIndex + deltaIndex * 10);
+ }
+
public int getMaxIndex() {
return mIndexMax;
}
@@ -1330,7 +1363,10 @@
if (mMuteCount == 0) {
// Register for client death notification
try {
- mICallback.linkToDeath(this, 0);
+ // mICallback can be 0 if muted by AudioService
+ if (mICallback != null) {
+ mICallback.linkToDeath(this, 0);
+ }
mDeathHandlers.add(this);
// If the stream is not yet muted by any client, set lvel to 0
if (muteCount() == 0) {
@@ -1356,9 +1392,12 @@
if (mMuteCount == 0) {
// Unregistr from client death notification
mDeathHandlers.remove(this);
- mICallback.unlinkToDeath(this, 0);
+ // mICallback can be 0 if muted by AudioService
+ if (mICallback != null) {
+ mICallback.unlinkToDeath(this, 0);
+ }
if (muteCount() == 0) {
- // If the stream is not mut any more, restore it's volume if
+ // If the stream is not muted any more, restore it's volume if
// ringer mode allows it
if (!isStreamAffectedByRingerMode(mStreamType) || mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
setIndex(mLastAudibleIndex, false);
@@ -1398,7 +1437,7 @@
int size = mDeathHandlers.size();
for (int i = 0; i < size; i++) {
handler = mDeathHandlers.get(i);
- if (cb.equals(handler.mICallback)) {
+ if (cb == handler.mICallback) {
return handler;
}
}
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 1d71577..7fb7db0 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -46,7 +46,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.util.Log;
+import android.util.Slog;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Xml;
@@ -150,7 +150,7 @@
maximumFailedPasswordsForWipe = Integer.parseInt(
parser.getAttributeValue(null, "value"));
} else {
- Log.w(TAG, "Unknown admin tag: " + tag);
+ Slog.w(TAG, "Unknown admin tag: " + tag);
}
XmlUtils.skipCurrentTag(parser);
}
@@ -165,8 +165,8 @@
pw.print(prefix); pw.print(" "); pw.println(pols.get(i).tag);
}
}
- pw.print(prefix); pw.print("passwordQuality=");
- pw.print(passwordQuality);
+ pw.print(prefix); pw.print("passwordQuality=0x");
+ pw.print(Integer.toHexString(passwordQuality));
pw.print(" minimumPasswordLength=");
pw.println(minimumPasswordLength);
pw.print(prefix); pw.print("maximumTimeToUnlock=");
@@ -185,7 +185,7 @@
int change = isPackageDisappearing(aa.info.getPackageName());
if (change == PACKAGE_PERMANENT_CHANGE
|| change == PACKAGE_TEMPORARY_CHANGE) {
- Log.w(TAG, "Admin unexpectedly uninstalled: "
+ Slog.w(TAG, "Admin unexpectedly uninstalled: "
+ aa.info.getComponent());
removed = true;
mAdminList.remove(i);
@@ -194,7 +194,7 @@
mContext.getPackageManager().getReceiverInfo(
aa.info.getComponent(), 0);
} catch (NameNotFoundException e) {
- Log.w(TAG, "Admin package change removed component: "
+ Slog.w(TAG, "Admin package change removed component: "
+ aa.info.getComponent());
removed = true;
mAdminList.remove(i);
@@ -308,10 +308,10 @@
try {
return new DeviceAdminInfo(mContext, infos.get(0));
} catch (XmlPullParserException e) {
- Log.w(TAG, "Bad device admin requested: " + adminName, e);
+ Slog.w(TAG, "Bad device admin requested: " + adminName, e);
return null;
} catch (IOException e) {
- Log.w(TAG, "Bad device admin requested: " + adminName, e);
+ Slog.w(TAG, "Bad device admin requested: " + adminName, e);
return null;
}
}
@@ -343,8 +343,6 @@
}
}
- out.endTag(null, "policies");
-
if (mPasswordOwner >= 0) {
out.startTag(null, "password-owner");
out.attribute(null, "value", Integer.toString(mPasswordOwner));
@@ -357,6 +355,15 @@
out.endTag(null, "failed-password-attempts");
}
+ if (mActivePasswordQuality != 0 || mActivePasswordLength != 0) {
+ out.startTag(null, "active-password");
+ out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
+ out.attribute(null, "length", Integer.toString(mActivePasswordLength));
+ out.endTag(null, "active-password");
+ }
+
+ out.endTag(null, "policies");
+
out.endDocument();
stream.close();
journal.commit();
@@ -410,7 +417,7 @@
mAdminList.add(ap);
}
} catch (RuntimeException e) {
- Log.w(TAG, "Failed loading admin " + name, e);
+ Slog.w(TAG, "Failed loading admin " + name, e);
}
} else if ("failed-password-attempts".equals(tag)) {
mFailedPasswordAttempts = Integer.parseInt(
@@ -420,21 +427,27 @@
mPasswordOwner = Integer.parseInt(
parser.getAttributeValue(null, "value"));
XmlUtils.skipCurrentTag(parser);
+ } else if ("active-password".equals(tag)) {
+ mActivePasswordQuality = Integer.parseInt(
+ parser.getAttributeValue(null, "quality"));
+ mActivePasswordLength = Integer.parseInt(
+ parser.getAttributeValue(null, "length"));
+ XmlUtils.skipCurrentTag(parser);
} else {
- Log.w(TAG, "Unknown tag: " + tag);
+ Slog.w(TAG, "Unknown tag: " + tag);
XmlUtils.skipCurrentTag(parser);
}
}
} catch (NullPointerException e) {
- Log.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(TAG, "failed parsing " + file + " " + e);
} catch (NumberFormatException e) {
- Log.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(TAG, "failed parsing " + file + " " + e);
} catch (XmlPullParserException e) {
- Log.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(TAG, "failed parsing " + file + " " + e);
} catch (IOException e) {
- Log.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(TAG, "failed parsing " + file + " " + e);
} catch (IndexOutOfBoundsException e) {
- Log.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(TAG, "failed parsing " + file + " " + e);
}
try {
if (stream != null) {
@@ -444,6 +457,20 @@
// Ignore
}
+ // Validate that what we stored for the password quality matches
+ // sufficiently what is currently set. Note that this is only
+ // a sanity check in case the two get out of sync; this should
+ // never normally happen.
+ LockPatternUtils utils = new LockPatternUtils(mContext);
+ if (utils.getActivePasswordQuality() < mActivePasswordQuality) {
+ Slog.w(TAG, "Active password quality 0x"
+ + Integer.toHexString(mActivePasswordQuality)
+ + " does not match actual quality 0x"
+ + Integer.toHexString(utils.getActivePasswordQuality()));
+ mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ mActivePasswordLength = 0;
+ }
+
validatePasswordOwnerLocked();
long timeMs = getMaximumTimeToLock(null);
@@ -453,10 +480,23 @@
try {
getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
} catch (RemoteException e) {
- Log.w(TAG, "Failure talking with power manager", e);
+ Slog.w(TAG, "Failure talking with power manager", e);
}
}
+ static void validateQualityConstant(int quality) {
+ switch (quality) {
+ case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ return;
+ }
+ throw new IllegalArgumentException("Invalid quality constant: 0x"
+ + Integer.toHexString(quality));
+ }
+
void validatePasswordOwnerLocked() {
if (mPasswordOwner >= 0) {
boolean haveOwner = false;
@@ -467,7 +507,7 @@
}
}
if (!haveOwner) {
- Log.w(TAG, "Previous password owner " + mPasswordOwner
+ Slog.w(TAG, "Previous password owner " + mPasswordOwner
+ " no longer active; disabling");
mPasswordOwner = -1;
}
@@ -557,15 +597,17 @@
}
}
- public void setPasswordQuality(ComponentName who, int mode) {
+ public void setPasswordQuality(ComponentName who, int quality) {
+ validateQualityConstant(quality);
+
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
- if (ap.passwordQuality != mode) {
- ap.passwordQuality = mode;
+ if (ap.passwordQuality != quality) {
+ ap.passwordQuality = quality;
saveSettingsLocked();
}
}
@@ -693,23 +735,27 @@
DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
quality = getPasswordQuality(null);
if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
- int adjQuality = LockPatternUtils.adjustPasswordMode(password, quality);
- if (adjQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
- Log.w(TAG, "resetPassword: password does not meet quality " + quality);
+ int realQuality = LockPatternUtils.computePasswordQuality(password);
+ if (realQuality < quality) {
+ Slog.w(TAG, "resetPassword: password quality 0x"
+ + Integer.toHexString(quality)
+ + " does not meet required quality 0x"
+ + Integer.toHexString(quality));
return false;
}
- quality = adjQuality;
+ quality = realQuality;
}
int length = getPasswordMinimumLength(null);
if (password.length() < length) {
- Log.w(TAG, "resetPassword: password does not meet length " + length);
+ Slog.w(TAG, "resetPassword: password length " + password.length()
+ + " does not meet required length " + length);
return false;
}
}
int callingUid = Binder.getCallingUid();
if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
- Log.w(TAG, "resetPassword: already set by another uid and not entered by user");
+ Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
return false;
}
@@ -719,11 +765,13 @@
try {
LockPatternUtils utils = new LockPatternUtils(mContext);
utils.saveLockPassword(password, quality);
- int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
- != 0 ? callingUid : -1;
- if (mPasswordOwner != newOwner) {
- mPasswordOwner = newOwner;
- saveSettingsLocked();
+ synchronized (this) {
+ int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
+ != 0 ? callingUid : -1;
+ if (mPasswordOwner != newOwner) {
+ mPasswordOwner = newOwner;
+ saveSettingsLocked();
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -754,7 +802,7 @@
try {
getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
} catch (RemoteException e) {
- Log.w(TAG, "Failure talking with power manager", e);
+ Slog.w(TAG, "Failure talking with power manager", e);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -807,7 +855,7 @@
try {
RecoverySystem.rebootWipeUserData(mContext);
} catch (IOException e) {
- Log.w(TAG, "Failed requesting data wipe", e);
+ Slog.w(TAG, "Failed requesting data wipe", e);
}
}
@@ -857,6 +905,8 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ validateQualityConstant(quality);
+
synchronized (this) {
if (mActivePasswordQuality != quality || mActivePasswordLength != length
|| mFailedPasswordAttempts != 0) {
@@ -864,10 +914,8 @@
try {
mActivePasswordQuality = quality;
mActivePasswordLength = length;
- if (mFailedPasswordAttempts != 0) {
- mFailedPasswordAttempts = 0;
- saveSettingsLocked();
- }
+ mFailedPasswordAttempts = 0;
+ saveSettingsLocked();
sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
} finally {
@@ -946,7 +994,8 @@
}
pw.println(" ");
- pw.print(" mActivePasswordQuality="); pw.println(mActivePasswordQuality);
+ pw.print(" mActivePasswordQuality=0x");
+ pw.println(Integer.toHexString(mActivePasswordQuality));
pw.print(" mActivePasswordLength="); pw.println(mActivePasswordLength);
pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
pw.print(" mPasswordOwner="); pw.println(mPasswordOwner);
diff --git a/services/java/com/android/server/EntropyService.java b/services/java/com/android/server/EntropyService.java
index 0a53e9c..81ae26f 100644
--- a/services/java/com/android/server/EntropyService.java
+++ b/services/java/com/android/server/EntropyService.java
@@ -48,14 +48,15 @@
* instead of periodically.
*/
public class EntropyService extends Binder {
- private static final String ENTROPY_FILENAME = getSystemDir() + "/entropy.dat";
private static final String TAG = "EntropyService";
private static final int ENTROPY_WHAT = 1;
private static final int ENTROPY_WRITE_PERIOD = 3 * 60 * 60 * 1000; // 3 hrs
- private static final String RANDOM_DEV = "/dev/urandom";
private static final long START_TIME = System.currentTimeMillis();
private static final long START_NANOTIME = System.nanoTime();
+ private final String randomDevice;
+ private final String entropyFile;
+
/**
* Handler that periodically updates the entropy on disk.
*/
@@ -72,6 +73,16 @@
};
public EntropyService() {
+ this(getSystemDir() + "/entropy.dat", "/dev/urandom");
+ }
+
+ /** Test only interface, not for public use */
+ public EntropyService(String entropyFile, String randomDevice) {
+ if (randomDevice == null) { throw new NullPointerException("randomDevice"); }
+ if (entropyFile == null) { throw new NullPointerException("entropyFile"); }
+
+ this.randomDevice = randomDevice;
+ this.entropyFile = entropyFile;
loadInitialEntropy();
addDeviceSpecificEntropy();
writeEntropy();
@@ -85,7 +96,7 @@
private void loadInitialEntropy() {
try {
- RandomBlock.fromFile(ENTROPY_FILENAME).toFile(RANDOM_DEV);
+ RandomBlock.fromFile(entropyFile).toFile(randomDevice);
} catch (IOException e) {
Slog.w(TAG, "unable to load initial entropy (first boot?)", e);
}
@@ -93,7 +104,7 @@
private void writeEntropy() {
try {
- RandomBlock.fromFile(RANDOM_DEV).toFile(ENTROPY_FILENAME);
+ RandomBlock.fromFile(randomDevice).toFile(entropyFile);
} catch (IOException e) {
Slog.w(TAG, "unable to write entropy", e);
}
@@ -116,7 +127,7 @@
private void addDeviceSpecificEntropy() {
PrintWriter out = null;
try {
- out = new PrintWriter(new FileOutputStream(RANDOM_DEV));
+ out = new PrintWriter(new FileOutputStream(randomDevice));
out.println("Copyright (C) 2009 The Android Open Source Project");
out.println("All Your Randomness Are Belong To Us");
out.println(START_TIME);
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index d50f591..a4703de 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -135,17 +135,6 @@
private static final int RETRY_UNMOUNT_DELAY = 30; // in ms
private static final int MAX_UNMOUNT_RETRIES = 4;
- private IntentFilter mPmFilter = new IntentFilter(
- Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- private BroadcastReceiver mPmReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
- mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
- }
- }
- };
-
class UnmountCallBack {
String path;
int retries;
@@ -200,49 +189,35 @@
class MountServiceHandler extends Handler {
ArrayList<UnmountCallBack> mForceUnmounts = new ArrayList<UnmountCallBack>();
- boolean mRegistered = false;
+ boolean mUpdatingStatus = false;
MountServiceHandler(Looper l) {
super(l);
}
- void registerReceiver() {
- mRegistered = true;
- if (DEBUG_UNMOUNT) Log.i(TAG, "Registering receiver");
- mContext.registerReceiver(mPmReceiver, mPmFilter);
- }
-
- void unregisterReceiver() {
- mRegistered = false;
- if (DEBUG_UNMOUNT) Log.i(TAG, "Unregistering receiver");
- mContext.unregisterReceiver(mPmReceiver);
- }
-
public void handleMessage(Message msg) {
switch (msg.what) {
case H_UNMOUNT_PM_UPDATE: {
if (DEBUG_UNMOUNT) Log.i(TAG, "H_UNMOUNT_PM_UPDATE");
UnmountCallBack ucb = (UnmountCallBack) msg.obj;
mForceUnmounts.add(ucb);
- if (DEBUG_UNMOUNT) Log.i(TAG, " registered = " + mRegistered);
+ if (DEBUG_UNMOUNT) Log.i(TAG, " registered = " + mUpdatingStatus);
// Register only if needed.
- if (!mRegistered) {
- registerReceiver();
- if (DEBUG_UNMOUNT) Log.i(TAG, "Updating external media status");
- boolean hasExtPkgs = mPms.updateExternalMediaStatus(false);
- if (!hasExtPkgs) {
- // Unregister right away
- mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
- }
+ if (!mUpdatingStatus) {
+ if (DEBUG_UNMOUNT) Log.i(TAG, "Updating external media status on PackageManager");
+ mUpdatingStatus = true;
+ mPms.updateExternalMediaStatus(false, true);
}
break;
}
case H_UNMOUNT_PM_DONE: {
if (DEBUG_UNMOUNT) Log.i(TAG, "H_UNMOUNT_PM_DONE");
- // Unregister now.
- if (mRegistered) {
- unregisterReceiver();
+ if (!mUpdatingStatus) {
+ // Does not correspond to unmount's status update.
+ return;
}
+ if (DEBUG_UNMOUNT) Log.i(TAG, "Updated status. Processing requests");
+ mUpdatingStatus = false;
int size = mForceUnmounts.size();
int sizeArr[] = new int[size];
int sizeArrN = 0;
@@ -261,7 +236,7 @@
ActivityManagerService ams = (ActivityManagerService)
ServiceManager.getService("activity");
// Eliminate system process here?
- boolean ret = ams.killPidsForMemory(pids);
+ boolean ret = ams.killPids(pids, "Unmount media");
if (ret) {
// Confirm if file references have been freed.
pids = getStorageUsers(path);
@@ -277,8 +252,8 @@
ucb));
} else {
if (ucb.retries >= MAX_UNMOUNT_RETRIES) {
- Log.i(TAG, "Cannot unmount inspite of " +
- MAX_UNMOUNT_RETRIES + " to unmount media");
+ Log.i(TAG, "Cannot unmount media inspite of " +
+ MAX_UNMOUNT_RETRIES + " retries");
// Send final broadcast indicating failure to unmount.
} else {
mHandler.sendMessageDelayed(
@@ -337,16 +312,23 @@
public void run() {
try {
String path = Environment.getExternalStorageDirectory().getPath();
- if (getVolumeState(
- Environment.getExternalStorageDirectory().getPath()).equals(
- Environment.MEDIA_UNMOUNTED)) {
+ String state = getVolumeState(path);
+
+ if (state.equals(Environment.MEDIA_UNMOUNTED)) {
int rc = doMountVolume(path);
if (rc != StorageResultCode.OperationSucceeded) {
Log.e(TAG, String.format("Boot-time mount failed (%d)", rc));
}
+ } else if (state.equals(Environment.MEDIA_SHARED)) {
+ /*
+ * Bootstrap UMS enabled state since vold indicates
+ * the volume is shared (runtime restart while ums enabled)
+ */
+ notifyVolumeStateChange(null, path, VolumeState.NoMedia, VolumeState.Shared);
}
+
/*
- * If UMS is connected in boot, send the connected event
+ * If UMS was connected on boot, send the connected event
* now that we're up.
*/
if (mSendUmsConnectedOnBoot) {
@@ -405,9 +387,9 @@
}
// Update state on PackageManager
if (Environment.MEDIA_UNMOUNTED.equals(state)) {
- mPms.updateExternalMediaStatus(false);
+ mPms.updateExternalMediaStatus(false, false);
} else if (Environment.MEDIA_MOUNTED.equals(state)) {
- mPms.updateExternalMediaStatus(true);
+ mPms.updateExternalMediaStatus(true, false);
}
String oldState = mLegacyState;
mLegacyState = state;
@@ -750,19 +732,15 @@
if (!getVolumeState(path).equals(Environment.MEDIA_MOUNTED)) {
return VoldResponseCode.OpFailedVolNotMounted;
}
-
- // We unmounted the volume. No of the asec containers are available now.
- synchronized (mAsecMountSet) {
- mAsecMountSet.clear();
- }
- // Notify PackageManager of potential media removal and deal with
- // return code later on. The caller of this api should be aware or have been
- // notified that the applications installed on the media will be killed.
// Redundant probably. But no harm in updating state again.
- mPms.updateExternalMediaStatus(false);
+ mPms.updateExternalMediaStatus(false, false);
try {
mConnector.doCommand(String.format(
"volume unmount %s%s", path, (force ? " force" : "")));
+ // We unmounted the volume. None of the asec containers are available now.
+ synchronized (mAsecMountSet) {
+ mAsecMountSet.clear();
+ }
return StorageResultCode.OperationSucceeded;
} catch (NativeDaemonConnectorException e) {
// Don't worry about mismatch in PackageManager since the
@@ -1225,7 +1203,10 @@
try {
mConnector.doCommand(cmd);
} catch (NativeDaemonConnectorException e) {
- rc = StorageResultCode.OperationFailedInternalError;
+ int code = e.getCode();
+ if (code != VoldResponseCode.OpFailedStorageBusy) {
+ rc = StorageResultCode.OperationFailedInternalError;
+ }
}
if (rc == StorageResultCode.OperationSucceeded) {
@@ -1325,5 +1306,9 @@
Log.e(TAG, "Got an empty response");
return "";
}
+
+ public void finishMediaUpdate() {
+ mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
+ }
}
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index 39c847a..08d7ce6 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -48,6 +48,8 @@
private String mSocket;
private INativeDaemonConnectorCallbacks mCallbacks;
+ private final int BUFFER_SIZE = 4096;
+
class ResponseCode {
public static final int ActionInitiated = 100;
@@ -87,7 +89,7 @@
}
private void listenToSocket() throws IOException {
- LocalSocket socket = null;
+ LocalSocket socket = null;
try {
socket = new LocalSocket();
@@ -100,13 +102,13 @@
InputStream inputStream = socket.getInputStream();
mOutputStream = socket.getOutputStream();
- byte[] buffer = new byte[4096];
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int start = 0;
while (true) {
- int count = inputStream.read(buffer);
+ int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
if (count < 0) break;
- int start = 0;
for (int i = 0; i < count; i++) {
if (buffer[i] == 0) {
String event = new String(buffer, start, i - start);
@@ -139,6 +141,13 @@
start = i + 1;
}
}
+ if (start != count) {
+ final int remaining = BUFFER_SIZE - start;
+ System.arraycopy(buffer, start, buffer, 0, remaining);
+ start = remaining;
+ } else {
+ start = 0;
+ }
}
} catch (IOException ex) {
Slog.e(TAG, "Communications error", ex);
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 48b3fbb..f9e1963 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -343,6 +343,7 @@
static final int POST_INSTALL = 9;
static final int MCS_RECONNECT = 10;
static final int MCS_GIVE_UP = 11;
+ static final int UPDATED_MEDIA_STATUS = 12;
// Delay time in millisecs
static final int BROADCAST_DELAY = 10 * 1000;
@@ -596,6 +597,13 @@
Slog.e(TAG, "Bogus post-install token " + msg.arg1);
}
} break;
+ case UPDATED_MEDIA_STATUS: {
+ try {
+ PackageHelper.getMountService().finishMediaUpdate();
+ } catch (RemoteException e) {
+ Log.e(TAG, "MountService not running?");
+ }
+ } break;
}
}
}
@@ -3969,7 +3977,7 @@
&& ps.permissionsFixed) {
// If this is an existing, non-system package, then
// we can't add any new permissions to it.
- if (!allowedSig && !gp.loadedPermissions.contains(perm)) {
+ if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
allowed = false;
// Except... if this is a permission that was added
// to the platform (note: need to only do this when
@@ -3981,7 +3989,7 @@
if (npi.name.equals(perm)
&& pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
allowed = true;
- Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
+ Log.i(TAG, "Auto-granting " + perm + " to old pkg "
+ pkg.packageName);
break;
}
@@ -4029,7 +4037,6 @@
// permissions we have now selected are fixed until explicitly
// changed.
ps.permissionsFixed = true;
- gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
}
}
@@ -6940,12 +6947,6 @@
pw.print(" "); pw.println(s);
}
}
- if (ps.loadedPermissions.size() > 0) {
- pw.println(" loadedPermissions:");
- for (String s : ps.loadedPermissions) {
- pw.print(" "); pw.println(s);
- }
- }
}
}
printedSomething = false;
@@ -7014,10 +7015,6 @@
for (String s : su.grantedPermissions) {
pw.print(" "); pw.println(s);
}
- pw.println(" loadedPermissions:");
- for (String s : su.loadedPermissions) {
- pw.print(" "); pw.println(s);
- }
}
}
@@ -7520,8 +7517,6 @@
HashSet<String> grantedPermissions = new HashSet<String>();
int[] gids;
- HashSet<String> loadedPermissions = new HashSet<String>();
-
GrantedPermissions(int pkgFlags) {
setFlags(pkgFlags);
}
@@ -7621,7 +7616,6 @@
public void copyFrom(PackageSettingBase base) {
grantedPermissions = base.grantedPermissions;
gids = base.gids;
- loadedPermissions = base.loadedPermissions;
timeStamp = base.timeStamp;
timeStampString = base.timeStampString;
@@ -8055,7 +8049,6 @@
p.userId = dis.userId;
// Clone permissions
p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
- p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
// Clone component info
p.disabledComponents = new HashSet<String>(dis.disabledComponents);
p.enabledComponents = new HashSet<String>(dis.enabledComponents);
@@ -8160,7 +8153,7 @@
}
for (PackageSetting pkg:sus.packages) {
if (pkg.pkg != null &&
- !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
+ !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) &&
pkg.pkg.requestedPermissions.contains(eachPerm)) {
used = true;
break;
@@ -8169,7 +8162,6 @@
if (!used) {
// can safely delete this permission from list
sus.grantedPermissions.remove(eachPerm);
- sus.loadedPermissions.remove(eachPerm);
}
}
// Update gids
@@ -9044,7 +9036,7 @@
packageSetting.signatures.readXml(parser, mPastSignatures);
} else if (tagName.equals("perms")) {
readGrantedPermissionsLP(parser,
- packageSetting.loadedPermissions);
+ packageSetting.grantedPermissions);
packageSetting.permissionsFixed = true;
} else {
reportSettingsProblem(Log.WARN,
@@ -9173,7 +9165,7 @@
if (tagName.equals("sigs")) {
su.signatures.readXml(parser, mPastSignatures);
} else if (tagName.equals("perms")) {
- readGrantedPermissionsLP(parser, su.loadedPermissions);
+ readGrantedPermissionsLP(parser, su.grantedPermissions);
} else {
reportSettingsProblem(Log.WARN,
"Unknown element under <shared-user>: "
@@ -9373,10 +9365,12 @@
}
/*
- * Return true if PackageManager does have packages to be updated.
+ * Update media status on PackageManager.
*/
- public boolean updateExternalMediaStatus(final boolean mediaStatus) {
- final boolean ret;
+ public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Media status can only be updated by the system");
+ }
synchronized (mPackages) {
Log.i(TAG, "Updating external media status from " +
(mMediaMounted ? "mounted" : "unmounted") + " to " +
@@ -9384,32 +9378,29 @@
if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
mediaStatus+", mMediaMounted=" + mMediaMounted);
if (mediaStatus == mMediaMounted) {
- return false;
+ if (reportStatus) {
+ mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS);
+ }
+ return;
}
mMediaMounted = mediaStatus;
- Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_EXTERNAL_STORAGE);
- ret = appList != null && appList.size() > 0;
- if (DEBUG_SD_INSTALL) {
- if (appList != null) {
- for (String app : appList) {
- Log.i(TAG, "Should enable " + app + " on sdcard");
- }
- }
- }
- if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus returning " + ret);
}
// Queue up an async operation since the package installation may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- updateExternalMediaStatusInner(mediaStatus, ret);
+ try {
+ updateExternalMediaStatusInner(mediaStatus);
+ } finally {
+ if (reportStatus) {
+ mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS);
+ }
+ }
}
});
- return ret;
}
- private void updateExternalMediaStatusInner(boolean mediaStatus,
- boolean sendUpdateBroadcast) {
+ private void updateExternalMediaStatusInner(boolean mediaStatus) {
// If we are up here that means there are packages to be
// enabled or disabled.
final String list[] = PackageHelper.getSecureContainerList();
@@ -9474,11 +9465,11 @@
// Process packages with valid entries.
if (mediaStatus) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
- loadMediaPackages(processCids, uidArr, sendUpdateBroadcast, removeCids);
+ loadMediaPackages(processCids, uidArr, removeCids);
startCleaningPackages();
} else {
if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
- unloadMediaPackages(processCids, uidArr, sendUpdateBroadcast);
+ unloadMediaPackages(processCids, uidArr);
}
}
@@ -9509,8 +9500,7 @@
* to avoid unnecessary crashes.
*/
private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids,
- int uidArr[], boolean sendUpdateBroadcast,
- HashSet<String> removeCids) {
+ int uidArr[], HashSet<String> removeCids) {
ArrayList<String> pkgList = new ArrayList<String>();
Set<SdInstallArgs> keys = processCids.keySet();
boolean doGc = false;
@@ -9553,8 +9543,6 @@
// Scan the package
if (scanPackageLI(pkg, parseFlags, SCAN_MONITOR) != null) {
synchronized (mPackages) {
- updatePermissionsLP(pkg.packageName, pkg,
- pkg.permissions.size() > 0, false);
retCode = PackageManager.INSTALL_SUCCEEDED;
pkgList.add(pkg.packageName);
// Post process args
@@ -9578,7 +9566,7 @@
mSettings.writeLP();
}
// Send a broadcast to let everyone know we are done processing
- if (sendUpdateBroadcast) {
+ if (pkgList.size() > 0) {
sendResourcesChangedBroadcast(true, pkgList, uidArr);
}
if (doGc) {
@@ -9594,7 +9582,7 @@
}
private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids,
- int uidArr[], boolean sendUpdateBroadcast) {
+ int uidArr[]) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
ArrayList<String> pkgList = new ArrayList<String>();
ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
@@ -9617,7 +9605,7 @@
}
}
// Send broadcasts
- if (sendUpdateBroadcast) {
+ if (pkgList.size() > 0) {
sendResourcesChangedBroadcast(false, pkgList, uidArr);
}
// Force gc
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index d72416d..848997b 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -571,6 +571,7 @@
binder = b;
tag = t;
uid = u == MY_UID ? Process.SYSTEM_UID : u;
+ pid = Binder.getCallingPid();
if (u != MY_UID || (
!"KEEP_SCREEN_ON_FLAG".equals(tag)
&& !"KeyInputQueue".equals(tag))) {
@@ -595,6 +596,7 @@
final IBinder binder;
final String tag;
final int uid;
+ final int pid;
final int monitorType;
boolean activated = true;
int minState;
@@ -998,7 +1000,8 @@
activated = " activated";
}
pw.println(" " + type + " '" + wl.tag + "'" + acquireCausesWakeup
- + activated + " (minState=" + wl.minState + ")");
+ + activated + " (minState=" + wl.minState + ", uid=" + wl.uid
+ + ", pid=" + wl.pid + ")");
}
pw.println();
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 93e45fc..fdb67f8 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -10755,7 +10755,7 @@
pids[i] = pidCandidates.keyAt(i);
}
try {
- if (mActivityManager.killPidsForMemory(pids)) {
+ if (mActivityManager.killPids(pids, "Free memory")) {
killedApps = true;
}
} catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2ecebed..7034c88 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -8359,11 +8359,11 @@
}
}
- public boolean killPidsForMemory(int[] pids) {
+ public boolean killPids(int[] pids, String pReason) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("killPidsForMemory only available to the system");
+ throw new SecurityException("killPids only available to the system");
}
-
+ String reason = (pReason == null) ? "Unknown" : pReason;
// XXX Note: don't acquire main activity lock here, because the window
// manager calls in with its locks held.
@@ -8387,7 +8387,7 @@
if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
worstType = HIDDEN_APP_MIN_ADJ;
}
- Slog.w(TAG, "Killing processes for memory at adjustment " + worstType);
+ Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
for (int i=0; i<pids.length; i++) {
ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
if (proc == null) {
@@ -8395,10 +8395,10 @@
}
int adj = proc.setAdj;
if (adj >= worstType) {
- Slog.w(TAG, "Killing for memory: " + proc + " (adj "
+ Slog.w(TAG, "Killing " + reason + " : " + proc + " (adj "
+ adj + ")");
- EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
- proc.processName, adj);
+ EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
+ proc.processName, adj, reason);
killed = true;
Process.killProcess(pids[i]);
}
diff --git a/services/java/com/android/server/am/EventLogTags.logtags b/services/java/com/android/server/am/EventLogTags.logtags
index 0ddcc247..aadd37d 100644
--- a/services/java/com/android/server/am/EventLogTags.logtags
+++ b/services/java/com/android/server/am/EventLogTags.logtags
@@ -58,7 +58,7 @@
# The activity's onResume has been called.
30022 am_on_resume_called (Component Name|3)
# Kill a process to reclaim memory.
-30023 am_kill_for_memory (PID|1|5),(Process Name|3),(OomAdj|1|5)
+30023 am_kill (PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3)
# Discard an undelivered serialized broadcast (timeout/ANR/crash)
30024 am_broadcast_discard_filter (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5)
30025 am_broadcast_discard_app (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3)
diff --git a/services/tests/servicestests/src/com/android/server/EntropyServiceTest.java b/services/tests/servicestests/src/com/android/server/EntropyServiceTest.java
new file mode 100644
index 0000000..636ba21
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/EntropyServiceTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.server;
+
+import android.content.Context;
+import android.os.FileUtils;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+
+/**
+ * Tests for {@link com.android.server.EntropyService}
+ */
+public class EntropyServiceTest extends AndroidTestCase {
+
+ public void testInitialWrite() throws Exception {
+ File dir = getContext().getDir("testInitialWrite", Context.MODE_PRIVATE);
+ File file = File.createTempFile("testInitialWrite", "dat", dir);
+ file.deleteOnExit();
+ assertEquals(0, FileUtils.readTextFile(file, 0, null).length());
+
+ // The constructor has the side effect of writing to file
+ new EntropyService("/dev/null", file.getCanonicalPath());
+
+ assertTrue(FileUtils.readTextFile(file, 0, null).length() > 0);
+ }
+}
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index b8ea4c0..a284ea5 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -237,8 +237,8 @@
/*
* TODO(cleanup): It would make some sense if the result of
- * preprocessing a message to determine the proper encoding (ie
- * the resulting datastructure from calculateLength) could be
+ * preprocessing a message to determine the proper encoding (i.e.
+ * the resulting data structure from calculateLength) could be
* passed as an argument to the actual final encoding function.
* This would better ensure that the logic behind size calculation
* actually matched the encoding.
@@ -427,7 +427,7 @@
* @param destinationAddress the address of the destination for the message
* @param destinationPort the port to deliver the message to at the
* destination
- * @param data the dat for the message
+ * @param data the data for the message
* @return a <code>SubmitPdu</code> containing the encoded SC
* address, if applicable, and the encoded message.
* Returns null on encode error.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ae5b1de..f018d107 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -46,7 +46,7 @@
* {@link android.content.Context#getSystemService
* Context.getSystemService(Context.TELEPHONY_SERVICE)}.
* <p>
- * Note that acess to some telephony information is
+ * Note that access to some telephony information is
* permission-protected. Your application cannot access the protected
* information unless it has the appropriate permissions declared in
* its manifest file. Where permissions apply, they are noted in the
@@ -356,7 +356,7 @@
}
/**
- * Returns the ISO country code equivilent of the current registered
+ * Returns the ISO country code equivalent of the current registered
* operator's MCC (Mobile Country Code).
* <p>
* Availability: Only when user is registered to a network. Result may be
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index 6eea46e..d3a34ec 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -202,7 +202,7 @@
/**
* Supply the ICC PIN to the ICC
*
- * When the operation is complete, onComplete will be sent to it's
+ * When the operation is complete, onComplete will be sent to its
* Handler.
*
* onComplete.obj will be an AsyncResult
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 358af95..a8f4143 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -585,7 +585,7 @@
/**
* Utility code to set the system locale if it's not set already
- * @param langauge Two character language code desired
+ * @param language Two character language code desired
* @param country Two character country code desired
*
* {@hide}
@@ -694,22 +694,22 @@
public void setTTYMode(int ttyMode, Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("setTTYMode");
}
public void queryTTYMode(Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("queryTTYMode");
}
public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
}
public void getEnhancedVoicePrivacy(Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
}
public void setBandMode(int bandMode, Message response) {
@@ -754,7 +754,7 @@
* Returns the CDMA ERI icon index to display
*/
public int getCdmaEriIconIndex() {
- Log.e(LOG_TAG, "Error! getCdmaEriIconIndex should never be executed in GSM mode");
+ logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
return -1;
}
@@ -764,7 +764,7 @@
* 1 - FLASHING
*/
public int getCdmaEriIconMode() {
- Log.e(LOG_TAG, "Error! getCdmaEriIconMode should never be executed in GSM mode");
+ logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
return -1;
}
@@ -772,82 +772,82 @@
* Returns the CDMA ERI text,
*/
public String getCdmaEriText() {
- Log.e(LOG_TAG, "Error! getCdmaEriText should never be executed in GSM mode");
+ logUnexpectedCdmaMethodCall("getCdmaEriText");
return "GSM nw, no ERI";
}
public String getCdmaMin() {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("getCdmaMin");
return null;
}
public boolean isMinInfoReady() {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("isMinInfoReady");
return false;
}
public String getCdmaPrlVersion(){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
return null;
}
public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("sendBurstDtmf");
}
public void exitEmergencyCallbackMode() {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
}
public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
}
public void unregisterForCdmaOtaStatusChange(Handler h) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
}
public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
}
public void unregisterForSubscriptionInfoReady(Handler h) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
}
public boolean isOtaSpNumber(String dialStr) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("isOtaSpNumber");
return false;
}
public void registerForCallWaiting(Handler h, int what, Object obj){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("registerForCallWaiting");
}
public void unregisterForCallWaiting(Handler h){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
}
public void registerForEcmTimerReset(Handler h, int what, Object obj) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
}
public void unregisterForEcmTimerReset(Handler h) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
}
public void registerForSignalInfo(Handler h, int what, Object obj) {
@@ -908,12 +908,12 @@
public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
}
public void unsetOnEcbModeExitResponse(Handler h){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
}
public String getInterfaceName(String apnType) {
@@ -984,7 +984,7 @@
}
/**
- * Notifiy registrants of a new ringing Connection.
+ * Notify registrants of a new ringing Connection.
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
@@ -1017,4 +1017,13 @@
+ " mCallRingContinueToken=" + mCallRingContinueToken);
}
}
+
+ /**
+ * Common error logger method for unexpected calls to CDMA-only methods.
+ */
+ private void logUnexpectedCdmaMethodCall(String name)
+ {
+ Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
+ "called, CDMAPhone inactive.");
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index 4a4282fc..764d12e 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -109,6 +109,12 @@
/** Stop the sending */
static final protected int EVENT_STOP_SENDING = 10;
+ /** Memory status reporting is acknowledged by RIL */
+ static final protected int EVENT_REPORT_MEMORY_STATUS_DONE = 11;
+
+ /** Radio is ON */
+ static final protected int EVENT_RADIO_ON = 12;
+
protected Phone mPhone;
protected Context mContext;
protected ContentResolver mResolver;
@@ -152,6 +158,7 @@
private SmsMessageBase.SubmitPduBase mSubmitPduBase;
protected boolean mStorageAvailable = true;
+ protected boolean mReportMemoryStatusPending = false;
protected static int getNextConcatenatedRef() {
sConcatenatedRef += 1;
@@ -235,6 +242,7 @@
mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);
mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
mCm.setOnIccSmsFull(this, EVENT_ICC_FULL, null);
+ mCm.registerForOn(this, EVENT_RADIO_ON, null);
// Don't always start message ref at 0.
sConcatenatedRef = new Random().nextInt(256);
@@ -253,6 +261,7 @@
mCm.unSetOnNewSMS(this);
mCm.unSetOnSmsStatus(this);
mCm.unSetOnIccSmsFull(this);
+ mCm.unregisterForOn(this);
}
protected void finalize() {
@@ -370,6 +379,26 @@
removeMessages(EVENT_ALERT_TIMEOUT, msg.obj);
}
break;
+
+ case EVENT_REPORT_MEMORY_STATUS_DONE:
+ ar = (AsyncResult)msg.obj;
+ if (ar.exception != null) {
+ mReportMemoryStatusPending = true;
+ Log.v(TAG, "Memory status report to modem pending : mStorageAvailable = "
+ + mStorageAvailable);
+ } else {
+ mReportMemoryStatusPending = false;
+ }
+ break;
+
+ case EVENT_RADIO_ON:
+ if (mReportMemoryStatusPending) {
+ Log.v(TAG, "Sending pending memory status report : mStorageAvailable = "
+ + mStorageAvailable);
+ mCm.reportSmsMemoryStatus(mStorageAvailable,
+ obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
+ }
+ break;
}
}
@@ -940,10 +969,10 @@
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_LOW)) {
mStorageAvailable = false;
- mCm.reportSmsMemoryStatus(false, null);
+ mCm.reportSmsMemoryStatus(false, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
} else if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_OK)) {
mStorageAvailable = true;
- mCm.reportSmsMemoryStatus(true, null);
+ mCm.reportSmsMemoryStatus(true, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
} else {
// Assume the intent is one of the SMS receive intents that
// was sent as an ordered broadcast. Check result and ACK.
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index dd7a169..6975c70 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -93,6 +93,9 @@
protected void setUp() throws Exception {
super.setUp();
mOrigState = getMediaState();
+ if (!mountMedia()) {
+ Log.i(TAG, "sdcard not mounted? Some of these tests might fail");
+ }
}
@Override
diff --git a/tests/ConnectivityManagerTest/Android.mk b/tests/ConnectivityManagerTest/Android.mk
new file mode 100644
index 0000000..bd773d0
--- /dev/null
+++ b/tests/ConnectivityManagerTest/Android.mk
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := ConnectivityManagerTest
+
+#LOCAL_INSTRUMENTATION_FOR := connectivitymanagertest
+
+include $(BUILD_PACKAGE)
diff --git a/tests/ConnectivityManagerTest/AndroidManifest.xml b/tests/ConnectivityManagerTest/AndroidManifest.xml
new file mode 100644
index 0000000..76b58e1
--- /dev/null
+++ b/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.connectivitymanagertest">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="ConnectivityManagerTestActivity"
+ android:label="CMTest">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TEST" />
+ </intent-filter>
+ </activity>
+ </application>
+ <!--
+ This declares that this app uses the instrumentation test runner targeting
+ the package of browserpowertest. To run the tests use the command:
+ "adb shell am instrument -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner"
+ -->
+ <instrumentation android:name=".ConnectivityManagerTestRunner"
+ android:targetPackage="com.android.connectivitymanagertest"
+ android:label="Test runner for Connectivity Manager Tests"
+ />
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+
+</manifest>
diff --git a/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
new file mode 100644
index 0000000..1dffa02
--- /dev/null
+++ b/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -0,0 +1,329 @@
+package com.android.connectivitymanagertest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import java.util.List;
+import android.widget.LinearLayout;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+
+
+/**
+ * An activity registered with connectivity manager broadcast
+ * provides network connectivity information and
+ * can be used to set device states: Cellular, Wifi, Airplane mode.
+ */
+public class ConnectivityManagerTestActivity extends Activity {
+
+ public static final String LOG_TAG = "ConnectivityManagerTestActivity";
+ public static final int WAIT_FOR_SCAN_RESULT = 5 * 1000; //5 seconds
+ public static final int WIFI_SCAN_TIMEOUT = 20 * 1000;
+ public ConnectivityReceiver mConnectivityReceiver = null;
+ public WifiReceiver mWifiReceiver = null;
+ /*
+ * Track network connectivity information
+ */
+ public State mState;
+ public NetworkInfo mNetworkInfo;
+ public NetworkInfo mOtherNetworkInfo;
+ public boolean mIsFailOver;
+ public String mReason;
+ public boolean mScanResultIsAvailable = false;
+ public ConnectivityManager mCM;
+
+ /*
+ * Control Wifi States
+ */
+ public WifiManager mWifiManager;
+
+ /*
+ * Verify connectivity state
+ */
+ public static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE;
+ NetworkState[] connectivityState = new NetworkState[NUM_NETWORK_TYPES];
+
+ /**
+ * A wrapper of a broadcast receiver which provides network connectivity information
+ * for all kinds of network: wifi, mobile, etc.
+ */
+ private class ConnectivityReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
+ return;
+ }
+
+ boolean noConnectivity =
+ intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
+
+ if (noConnectivity) {
+ mState = State.DISCONNECTED;
+ } else {
+ mState = State.CONNECTED;
+ }
+
+ mNetworkInfo = (NetworkInfo)
+ intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+
+ mOtherNetworkInfo = (NetworkInfo)
+ intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
+
+ mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
+ mIsFailOver = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
+ recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
+ if (mOtherNetworkInfo != null) {
+ recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState());
+ }
+ }
+ }
+
+ private class WifiReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (!action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+ Log.v(LOG_TAG, "onReceive() is calleld with " + intent);
+ return;
+ }
+ notifyScanResult();
+ }
+ }
+
+ public ConnectivityManagerTestActivity() {
+ mState = State.UNKNOWN;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.v(LOG_TAG, "onCreate, inst=" + Integer.toHexString(hashCode()));
+
+ // Create a simple layout
+ LinearLayout contentView = new LinearLayout(this);
+ contentView.setOrientation(LinearLayout.VERTICAL);
+ setContentView(contentView);
+ setTitle("ConnectivityManagerTestActivity");
+
+ mConnectivityReceiver = new ConnectivityReceiver();
+ // register a connectivity receiver for CONNECTIVITY_ACTION;
+ registerReceiver(mConnectivityReceiver,
+ new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+
+ mWifiReceiver = new WifiReceiver();
+ registerReceiver(mWifiReceiver,
+ new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+ // Get an instance of ConnectivityManager
+ mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
+ // Get an instance of WifiManager
+ mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE);
+ initializeNetworkStates();
+
+ if (mWifiManager.isWifiEnabled()) {
+ Log.v(LOG_TAG, "Clear Wifi before we start the test.");
+ clearWifi();
+ }
+ }
+
+ // for each network type, initialize network states to UNKNOWN, and no verification flag is set
+ public void initializeNetworkStates() {
+ for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
+ connectivityState[networkType] = new NetworkState();
+ Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " +
+ connectivityState[networkType].toString());
+ }
+ }
+
+ // deposit a network state
+ public void recordNetworkState(int networkType, State networkState) {
+ Log.v(LOG_TAG, "record network state for network " + networkType +
+ " state is " + networkState);
+ connectivityState[networkType].recordState(networkState);
+ }
+
+ // set the state transition criteria
+ public void setStateTransitionCriteria(int networkType, State initState,
+ int transitionDir, State targetState) {
+ connectivityState[networkType].setStateTransitionCriteria(
+ initState, transitionDir, targetState);
+ }
+
+ // Validate the states recorded
+ public boolean validateNetworkStates(int networkType) {
+ Log.v(LOG_TAG, "validate network state for " + networkType + ": ");
+ return connectivityState[networkType].validateStateTransition();
+ }
+
+ // return result from network state validation
+ public String getTransitionFailureReason(int networkType) {
+ Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " +
+ connectivityState[networkType].toString());
+ return connectivityState[networkType].getReason();
+ }
+
+ private void notifyScanResult() {
+ synchronized (this) {
+ Log.v(LOG_TAG, "notify that scan results are available");
+ this.notify();
+ }
+ }
+
+ // Return true if device is currently connected to mobile network
+ public boolean isConnectedToMobile() {
+ return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
+ }
+
+ // Return true if device is currently connected to Wifi
+ public boolean isConnectedToWifi() {
+ return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
+ }
+
+ public boolean enableWifi() {
+ return mWifiManager.setWifiEnabled(true);
+ }
+
+ /**
+ * Associate the device to given SSID
+ * If the device is already associated with a WiFi, disconnect and forget it,
+ * We don't verify whether the connection is successful or not, leave this to the test
+ */
+ public boolean connectToWifi(String knownSSID) {
+ //If Wifi is not enabled, enable it
+ if (!mWifiManager.isWifiEnabled()) {
+ Log.v(LOG_TAG, "Wifi is not enabled, enable it");
+ mWifiManager.setWifiEnabled(true);
+ }
+
+ List<ScanResult> netList = mWifiManager.getScanResults();
+ if (netList == null) {
+ // if no scan results are available, start active scan
+ mWifiManager.startScanActive();
+ mScanResultIsAvailable = false;
+ long startTime = System.currentTimeMillis();
+ while (!mScanResultIsAvailable) {
+ if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
+ return false;
+ }
+ // wait for the scan results to be available
+ synchronized (this) {
+ // wait for the scan result to be available
+ try {
+ this.wait(WAIT_FOR_SCAN_RESULT);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if ((mWifiManager.getScanResults() == null) ||
+ (mWifiManager.getScanResults().size() <= 0)) {
+ continue;
+ }
+ mScanResultIsAvailable = true;
+ }
+ }
+ }
+
+ netList = mWifiManager.getScanResults();
+ for (int i = 0; i < netList.size(); i++) {
+ ScanResult sr= netList.get(i);
+ if (sr.SSID.equals(knownSSID)) {
+ Log.v(LOG_TAG, "found " + knownSSID + " in the scan result list");
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = sr.SSID;
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ int networkId = mWifiManager.addNetwork(config);
+ mWifiManager.saveConfiguration();
+ // Connect to network by disabling others.
+ mWifiManager.enableNetwork(networkId, true);
+ mWifiManager.reconnect();
+ break;
+ }
+ }
+
+ List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
+ if (netConfList.size() <= 0) {
+ Log.v(LOG_TAG, knownSSID + " is not available");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Disable Wifi
+ * @return true if Wifi is disabled successfully
+ */
+ public boolean disableWiFi() {
+ return mWifiManager.setWifiEnabled(false);
+ }
+
+ /**
+ * Disconnect from the current Wifi and clear the configuration list
+ */
+ public boolean clearWifi() {
+ if (mWifiManager.isWifiEnabled()) {
+ //remove the current network Id
+ int curNetworkId = mWifiManager.getConnectionInfo().getNetworkId();
+ mWifiManager.removeNetwork(curNetworkId);
+ mWifiManager.saveConfiguration();
+
+ // remove other saved networks
+ List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
+ if (netConfList != null) {
+ Log.v(LOG_TAG, "remove configured network ids");
+ for (int i = 0; i < netConfList.size(); i++) {
+ WifiConfiguration conf = new WifiConfiguration();
+ conf = netConfList.get(i);
+ mWifiManager.removeNetwork(conf.networkId);
+ }
+ }
+ mWifiManager.saveConfiguration();
+ // disable Wifi
+ if (!mWifiManager.setWifiEnabled(false)) {
+ return false;
+ }
+ // wait for the actions to be completed
+ try {
+ Thread.sleep(5*1000);
+ } catch (InterruptedException e) {}
+ }
+ return true;
+ }
+
+ /**
+ * Set airplane mode
+ */
+ public void setAirplaneMode(Context context, boolean enableAM) {
+ //set the airplane mode
+ Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
+ enableAM ? 1 : 0);
+ // Post the intent
+ Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ intent.putExtra("state", enableAM);
+ context.sendBroadcast(intent);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ //Unregister receiver
+ if (mConnectivityReceiver != null) {
+ unregisterReceiver(mConnectivityReceiver);
+ }
+ if (mWifiReceiver != null) {
+ unregisterReceiver(mWifiReceiver);
+ }
+ Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
+ }
+}
diff --git a/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java b/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
new file mode 100644
index 0000000..3affa65
--- /dev/null
+++ b/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
@@ -0,0 +1,43 @@
+package com.android.connectivitymanagertest;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import android.util.Log;
+import com.android.connectivitymanagertest.functional.ConnectivityManagerMobileTest;
+
+import junit.framework.TestSuite;
+
+/**
+ * Instrumentation Test Runner for all connectivity manager tests.
+ *
+ * To run the connectivity manager tests:
+ *
+ * adb shell am instrument \
+ * -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner
+ */
+
+public class ConnectivityManagerTestRunner extends InstrumentationTestRunner {
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(ConnectivityManagerMobileTest.class);
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ return ConnectivityManagerTestRunner.class.getClassLoader();
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ String testSSID = (String) icicle.get("ssid");
+ if (testSSID != null) {
+ TEST_SSID = testSSID;
+ }
+ }
+
+ public String TEST_SSID = "GoogleGuest";
+}
diff --git a/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java b/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
new file mode 100644
index 0000000..925120e
--- /dev/null
+++ b/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
@@ -0,0 +1,177 @@
+package com.android.connectivitymanagertest;
+
+import android.net.NetworkInfo.State;
+import android.util.Log;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class NetworkState {
+ public static final int TO_DISCONNECTION = 0; // transition to disconnection
+ public static final int TO_CONNECTION = 1; // transition to connection
+ public static final int DO_NOTHING = -1; // no state change
+ private final String LOG_TAG = "NetworkState";
+ private List<State> mStateDepository;
+ private State mTransitionTarget;
+ private int mTransitionDirection;
+ private String mReason = null; // record mReason of state transition failure
+
+ public NetworkState() {
+ mStateDepository = new ArrayList<State>();
+ mTransitionDirection = DO_NOTHING;
+ mTransitionTarget = State.UNKNOWN;
+ }
+
+ public NetworkState(State currentState) {
+ mStateDepository = new ArrayList<State>();
+ mStateDepository.add(currentState);
+ mTransitionDirection = DO_NOTHING;
+ mTransitionTarget = State.UNKNOWN;
+ }
+
+ // Reinitialize the network state
+ public void resetNetworkState() {
+ mStateDepository.clear();
+ mTransitionDirection = DO_NOTHING;
+ mTransitionTarget = State.UNKNOWN;
+ }
+
+ // set the transition criteria, transitionDir could be:
+ // DO_NOTHING, TO_CONNECTION, TO_DISCONNECTION
+ public void setStateTransitionCriteria(State initState, int transitionDir, State targetState) {
+ if (!mStateDepository.isEmpty()) {
+ mStateDepository.clear();
+ }
+ mStateDepository.add(initState);
+ mTransitionDirection = transitionDir;
+ mTransitionTarget = targetState;
+ Log.v(LOG_TAG, "setStateTransitionCriteria: " + printStates());
+ }
+
+ public void recordState(State currentState) {
+ mStateDepository.add(currentState);
+ }
+
+ // Verify state transition
+ public boolean validateStateTransition() {
+ Log.v(LOG_TAG, "print state depository: " + printStates());
+ if (mTransitionDirection == DO_NOTHING) {
+ if (mStateDepository.isEmpty()) {
+ Log.v(LOG_TAG, "no state is recorded");
+ mReason = "no state is recorded.";
+ return false;
+ } else if (mStateDepository.size() > 1) {
+ Log.v(LOG_TAG, "no broadcast is expected, " +
+ "instead broadcast is probably received");
+ mReason = "no broadcast is expected, instead broadcast is probably received";
+ return false;
+ } else if (mStateDepository.get(0) != mTransitionTarget) {
+ Log.v(LOG_TAG, mTransitionTarget + " is expected, but it is " +
+ mStateDepository.get(0));
+ mReason = mTransitionTarget + " is expected, but it is " + mStateDepository.get(0);
+ return false;
+ }
+ return true;
+ } else if (mTransitionDirection == TO_CONNECTION) {
+ Log.v(LOG_TAG, "transition to CONNECTED");
+ return transitToConnection();
+ } else {
+ Log.v(LOG_TAG, "transition to DISCONNECTED");
+ return transitToDisconnection();
+ }
+ }
+
+ /*
+ * Transition from CONNECTED -> DISCONNECTED:
+ * CONNECTED->DISCONNECTING->DISCONNECTED
+ * return false if any state transition is not valid and save a message in mReason
+ */
+ public boolean transitToDisconnection () {
+ mReason = "states: " + printStates();
+ if (mStateDepository.get(0) != State.CONNECTED) {
+ mReason += " initial state should be CONNECTED, but it is " +
+ mStateDepository.get(0) + ".";
+ return false;
+ }
+ State lastState = mStateDepository.get(mStateDepository.size() - 1);
+ if ( lastState != mTransitionTarget) {
+ mReason += " the last state should be DISCONNECTED, but it is " + lastState;
+ return false;
+ }
+ for (int i = 1; i < mStateDepository.size() - 1; i++) {
+ State preState = mStateDepository.get(i-1);
+ State curState = mStateDepository.get(i);
+ if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) ||
+ (curState == State.DISCONNECTED))) {
+ continue;
+ } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) {
+ continue;
+ } else if ((preState == State.DISCONNECTED) && (curState == State.DISCONNECTED)) {
+ continue;
+ } else {
+ mReason += " Transition state from " + preState.toString() + " to " +
+ curState.toString() + " is not valid.";
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // DISCONNECTED->CONNECTING->CONNECTED
+ public boolean transitToConnection() {
+ mReason = "states: " + printStates();
+ if (mStateDepository.get(0) != State.DISCONNECTED) {
+ mReason += " initial state should be DISCONNECTED, but it is " +
+ mStateDepository.get(0) + ".";
+ return false;
+ }
+ State lastState = mStateDepository.get(mStateDepository.size() - 1);
+ if ( lastState != mTransitionTarget) {
+ mReason += " the last state should be CONNECTED, but it is " + lastState;
+ return false;
+ }
+ for (int i = 1; i < mStateDepository.size(); i++) {
+ State preState = mStateDepository.get(i-1);
+ State curState = mStateDepository.get(i);
+ if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) ||
+ (curState == State.CONNECTED))) {
+ continue;
+ } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) {
+ continue;
+ } else if ((preState == State.CONNECTED) && (curState == State.CONNECTED)) {
+ continue;
+ } else {
+ mReason += " Transition state from " + preState.toString() + " to " +
+ curState.toString() + " is not valid.";
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public List<State> getTransitionStates() {
+ return mStateDepository;
+ }
+
+ // return state failure mReason
+ public String getReason() {
+ return mReason;
+ }
+
+ public String printStates() {
+ StringBuilder stateBuilder = new StringBuilder("");
+ for (int i = 0; i < mStateDepository.size(); i++) {
+ stateBuilder.append(" ").append(mStateDepository.get(i).toString()).append("->");
+ }
+ return stateBuilder.toString();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder(" ");
+ builder.append("mTransitionDirection: ").append(Integer.toString(mTransitionDirection)).
+ append("; ").append("states:").
+ append(printStates()).append("; ");
+ return builder.toString();
+ }
+}
diff --git a/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
new file mode 100644
index 0000000..ab81bb8
--- /dev/null
+++ b/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -0,0 +1,135 @@
+package com.android.connectivitymanagertest.functional;
+
+import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+
+import android.content.Intent;
+import android.content.Context;
+import android.app.Instrumentation;
+import android.os.Handler;
+import android.os.Message;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+import android.net.NetworkInfo.DetailedState;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.ActivityInstrumentationTestCase2;
+import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
+import com.android.connectivitymanagertest.NetworkState;
+import android.util.Log;
+import junit.framework.*;
+
+public class ConnectivityManagerMobileTest
+ extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+
+ private static final String LOG_TAG = "ConnectivityManagerMobileTest";
+ private static final String PKG_NAME = "com.android.connectivitymanagertest";
+ private static final long WIFI_CONNECTION_TIMEOUT = 30 * 1000;
+ private static final long WIFI_NOTIFICATION_TIMEOUT = 10 * 1000;
+ private String TEST_ACCESS_POINT;
+ private ConnectivityManagerTestActivity cmActivity;
+
+ public ConnectivityManagerMobileTest() {
+ super(PKG_NAME, ConnectivityManagerTestActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ cmActivity = getActivity();
+ ConnectivityManagerTestRunner mRunner =
+ (ConnectivityManagerTestRunner)getInstrumentation();
+ TEST_ACCESS_POINT = mRunner.TEST_SSID;
+ // Each test case will start with cellular connection
+ verifyCellularConnection();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ // clear Wifi after each test case
+ cmActivity.clearWifi();
+ cmActivity.finish();
+ Log.v(LOG_TAG, "tear down ConnectivityManager test activity");
+ super.tearDown();
+ }
+
+ // help function to verify 3G connection
+ public void verifyCellularConnection() {
+ NetworkInfo extraNetInfo = cmActivity.mNetworkInfo;
+ assertEquals("network type is not MOBILE", ConnectivityManager.TYPE_MOBILE,
+ extraNetInfo.getType());
+ assertTrue("not connected to cellular network", extraNetInfo.isConnected());
+ assertTrue("no data connection", cmActivity.mState.equals(State.CONNECTED));
+ }
+
+ // Test case 1: Test enabling Wifi without associating with any AP
+ @LargeTest
+ public void test3GToWifiNotification() {
+ // As Wifi stays in DISCONNECTED, the connectivity manager will not broadcast
+ // any network connectivity event for Wifi
+ NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+ cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, networkInfo.getState(),
+ NetworkState.DO_NOTHING, State.CONNECTED);
+ networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
+ NetworkState.DO_NOTHING, State.DISCONNECTED);
+ // Eanble Wifi
+ cmActivity.enableWifi();
+ try {
+ Thread.sleep(WIFI_NOTIFICATION_TIMEOUT);
+ } catch (Exception e) {
+ Log.v(LOG_TAG, "exception: " + e.toString());
+ }
+
+ // validate state and broadcast
+ if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+ Log.v(LOG_TAG, "the state for WIFI is changed");
+ Log.v(LOG_TAG, "reason: " +
+ cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+ assertTrue(false);
+ }
+ if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
+ Log.v(LOG_TAG, "the state for MOBILE is changed");
+ Log.v(LOG_TAG, "reason: " +
+ cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
+ assertTrue(false);
+ }
+ // Verify that the device is still connected to MOBILE
+ verifyCellularConnection();
+ }
+
+ // Test case 2: test connection to a given AP
+ @LargeTest
+ public void testConnectToWifi() {
+ //Prepare for connectivity verification
+ NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+ cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, networkInfo.getState(),
+ NetworkState.TO_DISCONNECTION, State.DISCONNECTED);
+ networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
+ NetworkState.TO_CONNECTION, State.CONNECTED);
+
+ // Enable Wifi and connect to a test access point
+ assertTrue("failed to connect to " + TEST_ACCESS_POINT,
+ cmActivity.connectToWifi(TEST_ACCESS_POINT));
+ try {
+ Thread.sleep(WIFI_CONNECTION_TIMEOUT);
+ } catch (Exception e) {
+ Log.v(LOG_TAG, "exception: " + e.toString());
+ }
+
+ // validate states
+ if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+ Log.v(LOG_TAG, "Wifi state transition validation failed.");
+ Log.v(LOG_TAG, "reason: " +
+ cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+ assertTrue(false);
+ }
+ if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
+ Log.v(LOG_TAG, "Mobile state transition validation failed.");
+ Log.v(LOG_TAG, "reason: " +
+ cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
+ assertTrue(false);
+ }
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index abae65d..80b8aedfa 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -54,10 +54,11 @@
import android.database.ContentObserver;
import com.android.internal.app.IBatteryStats;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Set;
import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Track the state of Wifi connectivity. All event handling is done here,
@@ -282,8 +283,13 @@
* {@link WifiManager#WIFI_STATE_ENABLED},
* {@link WifiManager#WIFI_STATE_ENABLING},
* {@link WifiManager#WIFI_STATE_UNKNOWN}
+ *
+ * getWifiState() is not synchronized to make sure it's always fast,
+ * even when the instance lock is held on other slow operations.
+ * Use a atomic variable for state.
*/
- private int mWifiState;
+ private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_UNKNOWN);
+
// Wi-Fi run states:
private static final int RUN_STATE_STARTING = 1;
private static final int RUN_STATE_RUNNING = 2;
@@ -785,8 +791,8 @@
case EVENT_SUPPLICANT_DISCONNECT:
mRunState = RUN_STATE_STOPPED;
noteRunState();
- boolean died = mWifiState != WIFI_STATE_DISABLED &&
- mWifiState != WIFI_STATE_DISABLING;
+ boolean died = mWifiState.get() != WIFI_STATE_DISABLED &&
+ mWifiState.get() != WIFI_STATE_DISABLING;
if (died) {
if (LOCAL_LOGD) Log.v(TAG, "Supplicant died unexpectedly");
} else {
@@ -1504,12 +1510,12 @@
return true;
}
- public synchronized int getWifiState() {
- return mWifiState;
+ public int getWifiState() {
+ return mWifiState.get();
}
- public synchronized void setWifiState(int wifiState) {
- mWifiState = wifiState;
+ public void setWifiState(int wifiState) {
+ mWifiState.set(wifiState);
}
/**
@@ -1588,7 +1594,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean ping() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.pingCommand();
@@ -1601,7 +1607,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean scan(boolean forceActive) {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.scanCommand(forceActive);
@@ -1617,7 +1623,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean setScanResultHandling(int mode) {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.setScanResultHandlingCommand(mode);
@@ -1631,7 +1637,7 @@
* 00:bb:cc:dd:cc:ff 2412 165 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net2
*/
public synchronized String scanResults() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return null;
}
return WifiNative.scanResultsCommand();
@@ -1643,7 +1649,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean setScanMode(boolean isScanModeActive) {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
if (mIsScanModeActive != isScanModeActive) {
@@ -1658,7 +1664,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean disconnect() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.disconnectCommand();
@@ -1670,7 +1676,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean reconnectCommand() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.reconnectCommand();
@@ -1682,7 +1688,7 @@
* @return network id of the new network
*/
public synchronized int addNetwork() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return -1;
}
return WifiNative.addNetworkCommand();
@@ -1695,7 +1701,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean removeNetwork(int networkId) {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return mDisconnectExpected = WifiNative.removeNetworkCommand(networkId);
@@ -1709,7 +1715,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean enableNetwork(int netId, boolean disableOthers) {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.enableNetworkCommand(netId, disableOthers);
@@ -1722,7 +1728,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean disableNetwork(int netId) {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.disableNetworkCommand(netId);
@@ -1734,7 +1740,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean reassociate() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.reassociateCommand();
@@ -1748,7 +1754,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean addToBlacklist(String bssid) {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.addToBlacklistCommand(bssid);
@@ -1760,7 +1766,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean clearBlacklist() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.clearBlacklistCommand();
@@ -1772,7 +1778,7 @@
* @return list of networks or null on failure
*/
public synchronized String listNetworks() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return null;
}
return WifiNative.listNetworksCommand();
@@ -1786,7 +1792,7 @@
* @return value corresponding to key
*/
public synchronized String getNetworkVariable(int netId, String name) {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return null;
}
return WifiNative.getNetworkVariableCommand(netId, name);
@@ -1801,7 +1807,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean setNetworkVariable(int netId, String name, String value) {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.setNetworkVariableCommand(netId, name, value);
@@ -1821,7 +1827,7 @@
* ip_address=X.X.X.X
*/
public synchronized String status() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return null;
}
return WifiNative.statusCommand();
@@ -1833,7 +1839,7 @@
* @return RSSI value, -1 on failure
*/
public synchronized int getRssi() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return -1;
}
return WifiNative.getRssiApproxCommand();
@@ -1845,7 +1851,7 @@
* @return RSSI value, -1 on failure
*/
public synchronized int getRssiApprox() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return -1;
}
return WifiNative.getRssiApproxCommand();
@@ -1857,7 +1863,7 @@
* @return link speed, -1 on failure
*/
public synchronized int getLinkSpeed() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return -1;
}
return WifiNative.getLinkSpeedCommand();
@@ -1869,7 +1875,7 @@
* @return MAC address, null on failure
*/
public synchronized String getMacAddress() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return null;
}
return WifiNative.getMacAddressCommand();
@@ -1881,7 +1887,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean startDriver() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.startDriverCommand();
@@ -1893,7 +1899,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean stopDriver() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.stopDriverCommand();
@@ -1905,7 +1911,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean startPacketFiltering() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.startPacketFiltering();
@@ -1917,7 +1923,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean stopPacketFiltering() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.stopPacketFiltering();
@@ -1931,7 +1937,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean setPowerMode(int mode) {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.setPowerModeCommand(mode);
@@ -1944,7 +1950,7 @@
* the number of channels is invalid.
*/
public synchronized boolean setNumAllowedChannels() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
try {
@@ -1969,7 +1975,7 @@
* {@code numChannels} is outside the valid range.
*/
public synchronized boolean setNumAllowedChannels(int numChannels) {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
mNumAllowedChannels = numChannels;
@@ -1982,7 +1988,7 @@
* @return channel count, -1 on failure
*/
public synchronized int getNumAllowedChannels() {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return -1;
}
return WifiNative.getNumAllowedChannelsCommand();
@@ -1998,7 +2004,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean setBluetoothCoexistenceMode(int mode) {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return false;
}
return WifiNative.setBluetoothCoexistenceModeCommand(mode);
@@ -2012,7 +2018,7 @@
* @param isBluetoothPlaying whether to enable or disable this mode
*/
public synchronized void setBluetoothScanMode(boolean isBluetoothPlaying) {
- if (mWifiState != WIFI_STATE_ENABLED && !isDriverStopped()) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED && !isDriverStopped()) {
return;
}
WifiNative.setBluetoothCoexistenceScanModeCommand(isBluetoothPlaying);
@@ -2024,7 +2030,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean saveConfig() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.saveConfigCommand();
@@ -2036,7 +2042,7 @@
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public synchronized boolean reloadConfig() {
- if (mWifiState != WIFI_STATE_ENABLED) {
+ if (mWifiState.get() != WIFI_STATE_ENABLED) {
return false;
}
return WifiNative.reloadConfigCommand();