diff options
100 files changed, 2077 insertions, 572 deletions
diff --git a/api/current.txt b/api/current.txt index cc7f07988404..d83659f64922 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4145,6 +4145,7 @@ package android.appwidget { ctor public AppWidgetHostView(android.content.Context, int, int); method public int getAppWidgetId(); method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(); + method public static android.graphics.Rect getDefaultPaddingForWidget(android.content.Context, android.content.ComponentName, android.graphics.Rect); method protected android.view.View getDefaultView(); method protected android.view.View getErrorView(); method protected void prepareView(android.view.View); @@ -4474,10 +4475,12 @@ package android.bluetooth { method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; method public int describeContents(); + method public boolean fetchUuidsWithSdp(); method public java.lang.String getAddress(); method public android.bluetooth.BluetoothClass getBluetoothClass(); method public int getBondState(); method public java.lang.String getName(); + method public android.os.ParcelUuid[] getUuids(); method public void writeToParcel(android.os.Parcel, int); field public static final java.lang.String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED"; field public static final java.lang.String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED"; @@ -4486,6 +4489,7 @@ package android.bluetooth { field public static final java.lang.String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED"; field public static final java.lang.String ACTION_FOUND = "android.bluetooth.device.action.FOUND"; field public static final java.lang.String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED"; + field public static final java.lang.String ACTION_UUID = "android.bluetooth.device.action.UUID"; field public static final int BOND_BONDED = 12; // 0xc field public static final int BOND_BONDING = 11; // 0xb field public static final int BOND_NONE = 10; // 0xa @@ -4497,6 +4501,7 @@ package android.bluetooth { field public static final java.lang.String EXTRA_NAME = "android.bluetooth.device.extra.NAME"; field public static final java.lang.String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE"; field public static final java.lang.String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI"; + field public static final java.lang.String EXTRA_UUID = "android.bluetooth.device.extra.UUID"; } public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile { @@ -8792,6 +8797,7 @@ package android.graphics { method public long getTimestamp(); method public void getTransformMatrix(float[]); method public void release(); + method public void setDefaultBufferSize(int, int); method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener); method public void updateTexImage(); } @@ -16606,6 +16612,10 @@ package android.provider { field public static final java.lang.String PHOTO_FILE_ID = "data14"; } + public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns { + field public static final java.lang.String CONTENT_DIRECTORY = "stream_items"; + } + protected static abstract interface ContactsContract.ContactsColumns { field public static final java.lang.String DISPLAY_NAME = "display_name"; field public static final java.lang.String HAS_PHONE_NUMBER = "has_phone_number"; @@ -16863,6 +16873,10 @@ package android.provider { field public static final java.lang.String DATA_ID = "data_id"; } + public static final class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns { + field public static final java.lang.String CONTENT_DIRECTORY = "stream_items"; + } + protected static abstract interface ContactsContract.RawContactsColumns { field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode"; field public static final java.lang.String CONTACT_ID = "contact_id"; @@ -16926,6 +16940,56 @@ package android.provider { field public static final android.net.Uri PROFILE_CONTENT_URI; } + public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { + field public static final java.lang.String PHOTO = "photo"; + } + + protected static abstract interface ContactsContract.StreamItemPhotosColumns { + field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id"; + field public static final java.lang.String PHOTO_URI = "photo_uri"; + field public static final java.lang.String SORT_INDEX = "sort_index"; + field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id"; + field public static final java.lang.String SYNC1 = "stream_item_photo_sync1"; + field public static final java.lang.String SYNC2 = "stream_item_photo_sync2"; + field public static final java.lang.String SYNC3 = "stream_item_photo_sync3"; + field public static final java.lang.String SYNC4 = "stream_item_photo_sync4"; + } + + public static final class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns { + field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item"; + field public static final android.net.Uri CONTENT_LIMIT_URI; + field public static final android.net.Uri CONTENT_PHOTO_URI; + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item"; + field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String MAX_ITEMS = "max_items"; + } + + public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { + field public static final java.lang.String CONTENT_DIRECTORY = "photo"; + field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo"; + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo"; + } + + protected static abstract interface ContactsContract.StreamItemsColumns { + field public static final java.lang.String ACCOUNT_NAME = "account_name"; + field public static final java.lang.String ACCOUNT_TYPE = "account_type"; + field public static final java.lang.String COMMENTS = "comments"; + field public static final java.lang.String CONTACT_ID = "contact_id"; + field public static final java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup"; + field public static final java.lang.String DATA_SET = "data_set"; + field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id"; + field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id"; + field public static final java.lang.String RES_ICON = "icon"; + field public static final java.lang.String RES_LABEL = "label"; + field public static final java.lang.String RES_PACKAGE = "res_package"; + field public static final java.lang.String SYNC1 = "stream_item_sync1"; + field public static final java.lang.String SYNC2 = "stream_item_sync2"; + field public static final java.lang.String SYNC3 = "stream_item_sync3"; + field public static final java.lang.String SYNC4 = "stream_item_sync4"; + field public static final java.lang.String TEXT = "text"; + field public static final java.lang.String TIMESTAMP = "timestamp"; + } + protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns { field public static final java.lang.String ACCOUNT_NAME = "account_name"; field public static final java.lang.String ACCOUNT_TYPE = "account_type"; @@ -17363,6 +17427,7 @@ package android.provider { field public static final java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled"; field public static final java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern"; field public static final deprecated java.lang.String LOGGING_ID = "logging_id"; + field public static final java.lang.String MESSAGING_APP_NOTIFICATIONS = "messaging_app_notifications"; field public static final java.lang.String NETWORK_PREFERENCE = "network_preference"; field public static final java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled"; field public static final java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update"; diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 4f722893d453..7c03a2ff2020 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -109,6 +109,10 @@ public class Am { runStartService(); } else if (op.equals("force-stop")) { runForceStop(); + } else if (op.equals("kill")) { + runKill(); + } else if (op.equals("kill-all")) { + runKillAll(); } else if (op.equals("instrument")) { runInstrument(); } else if (op.equals("broadcast")) { @@ -484,6 +488,14 @@ public class Am { mAm.forceStopPackage(nextArgRequired()); } + private void runKill() throws Exception { + mAm.killBackgroundProcesses(nextArgRequired()); + } + + private void runKillAll() throws Exception { + mAm.killAllBackgroundProcesses(); + } + private void sendBroadcast() throws Exception { Intent intent = makeIntent(); IntentReceiver receiver = new IntentReceiver(); @@ -1179,6 +1191,8 @@ public class Am { " [--R COUNT] [-S] <INTENT>\n" + " am startservice <INTENT>\n" + " am force-stop <PACKAGE>\n" + + " am kill <PACKAGE>\n" + + " am kill-all\n" + " am broadcast <INTENT>\n" + " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" + " [--no-window-animation] <COMPONENT>\n" + @@ -1202,6 +1216,12 @@ public class Am { "\n" + "am force-stop: force stop everything associated with <PACKAGE>.\n" + "\n" + + "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" + + " processes that are safe to kill -- that is, will not impact the user\n" + + " experience.\n" + + "\n" + + "am kill-all: Kill all background processes.\n" + + "\n" + "am broadcast: send a broadcast Intent.\n" + "\n" + "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" + diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp index 2378345821c2..bd430d182d53 100644 --- a/cmds/stagefright/stream.cpp +++ b/cmds/stagefright/stream.cpp @@ -360,7 +360,7 @@ int main(int argc, char **argv) { service->create(getpid(), client, 0); if (player != NULL && player->setDataSource(source) == NO_ERROR) { - player->setVideoSurface(surface); + player->setVideoSurfaceTexture(surface->getSurfaceTexture()); player->start(); client->waitForEOS(); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index b4471f096ad5..7994d7cd3bfb 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1092,6 +1092,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } + + case KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + killAllBackgroundProcesses(); + reply.writeNoException(); + return true; + } case FORCE_STOP_PACKAGE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); @@ -2906,7 +2913,7 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - + public void killBackgroundProcesses(String packageName) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -2917,7 +2924,17 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - + + public void killAllBackgroundProcesses() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + public void forceStopPackage(String packageName) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 00fe953f70e3..a4714cab3542 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3832,11 +3832,16 @@ public final class ActivityThread { * Initialize the default http proxy in this process for the reasons we set the time zone. */ IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); - try { - ProxyProperties proxyProperties = service.getProxy(); - Proxy.setHttpProxySystemProperty(proxyProperties); - } catch (RemoteException e) {} + if (b != null) { + // In pre-boot mode (doing initial launch to collect password), not + // all system is up. This includes the connectivity service, so don't + // crash if we can't get it. + IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); + try { + ProxyProperties proxyProperties = service.getProxy(); + Proxy.setHttpProxySystemProperty(proxyProperties); + } catch (RemoteException e) {} + } if (data.instrumentationName != null) { ContextImpl appContext = new ContextImpl(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 26813bf117df..5222d375a439 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -234,6 +234,7 @@ public interface IActivityManager extends IInterface { public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException; public void killBackgroundProcesses(final String packageName) throws RemoteException; + public void killAllBackgroundProcesses() throws RemoteException; public void forceStopPackage(final String packageName) throws RemoteException; // Note: probably don't want to allow applications access to these. @@ -605,4 +606,5 @@ public interface IActivityManager extends IInterface { int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136; int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137; int DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+138; + int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139; } diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 761c7eb0863c..61a9dce98d57 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -26,6 +26,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Rect; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -41,8 +42,8 @@ import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.FrameLayout; import android.widget.RemoteViews; -import android.widget.TextView; import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback; +import android.widget.TextView; /** * Provides the glue to show AppWidget views. This class offers automatic animation @@ -106,7 +107,9 @@ public class AppWidgetHostView extends FrameLayout { } /** - * Set the AppWidget that will be displayed by this view. + * Set the AppWidget that will be displayed by this view. This method also adds default padding + * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)} + * and can be overridden in order to add custom padding. */ public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) { mAppWidgetId = appWidgetId; @@ -116,49 +119,57 @@ public class AppWidgetHostView extends FrameLayout { // a widget, eg. for some widgets in safe mode. if (info != null) { // We add padding to the AppWidgetHostView if necessary - Padding padding = getPaddingForWidget(info.provider); + Rect padding = getDefaultPaddingForWidget(mContext, info.provider, null); setPadding(padding.left, padding.top, padding.right, padding.bottom); } } - private static class Padding { - int left = 0; - int right = 0; - int top = 0; - int bottom = 0; - } - /** * As of ICE_CREAM_SANDWICH we are automatically adding padding to widgets targeting * ICE_CREAM_SANDWICH and higher. The new widget design guidelines strongly recommend * that widget developers do not add extra padding to their widgets. This will help * achieve consistency among widgets. + * + * Note: this method is only needed by developers of AppWidgetHosts. The method is provided in + * order for the AppWidgetHost to account for the automatic padding when computing the number + * of cells to allocate to a particular widget. + * + * @param context the current context + * @param component the component name of the widget + * @param padding Rect in which to place the output, if null, a new Rect will be allocated and + * returned + * @return default padding for this widget */ - private Padding getPaddingForWidget(ComponentName component) { - PackageManager packageManager = mContext.getPackageManager(); - Padding p = new Padding(); + public static Rect getDefaultPaddingForWidget(Context context, ComponentName component, + Rect padding) { + PackageManager packageManager = context.getPackageManager(); ApplicationInfo appInfo; + if (padding == null) { + padding = new Rect(0, 0, 0, 0); + } else { + padding.set(0, 0, 0, 0); + } + try { appInfo = packageManager.getApplicationInfo(component.getPackageName(), 0); - } catch (Exception e) { + } catch (NameNotFoundException e) { // if we can't find the package, return 0 padding - return p; + return padding; } if (appInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - Resources r = getResources(); - p.left = r.getDimensionPixelSize(com.android.internal. + Resources r = context.getResources(); + padding.left = r.getDimensionPixelSize(com.android.internal. R.dimen.default_app_widget_padding_left); - p.right = r.getDimensionPixelSize(com.android.internal. + padding.right = r.getDimensionPixelSize(com.android.internal. R.dimen.default_app_widget_padding_right); - p.top = r.getDimensionPixelSize(com.android.internal. + padding.top = r.getDimensionPixelSize(com.android.internal. R.dimen.default_app_widget_padding_top); - p.bottom = r.getDimensionPixelSize(com.android.internal. + padding.bottom = r.getDimensionPixelSize(com.android.internal. R.dimen.default_app_widget_padding_bottom); } - - return p; + return padding; } public int getAppWidgetId() { diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 4cb822047918..03065218ee92 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -247,13 +247,12 @@ public final class BluetoothDevice implements Parcelable { * has been fetched. This intent is sent only when the UUIDs of the remote * device are requested to be fetched using Service Discovery Protocol * <p> Always contains the extra field {@link #EXTRA_DEVICE} - * <p> Always contains the extra filed {@link #EXTRA_UUID} + * <p> Always contains the extra field {@link #EXTRA_UUID} * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. - * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_UUID = - "android.bleutooth.device.action.UUID"; + "android.bluetooth.device.action.UUID"; /** * Broadcast Action: Indicates a failure to retrieve the name of a remote @@ -451,7 +450,6 @@ public final class BluetoothDevice implements Parcelable { * Used as an extra field in {@link #ACTION_UUID} intents, * Contains the {@link android.os.ParcelUuid}s of the remote device which * is a parcelable version of {@link UUID}. - * @hide */ public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID"; @@ -770,7 +768,18 @@ public final class BluetoothDevice implements Parcelable { return false; } - /** @hide */ + /** + * Returns the supported features (UUIDs) of the remote device. + * + * <p>This method does not start a service discovery procedure to retrieve the UUIDs + * from the remote device. Instead, the local cached copy of the service + * UUIDs are returned. + * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. + * + * @return the supported features (UUIDs) of the remote device, + * or null on error + */ public ParcelUuid[] getUuids() { try { return sService.getRemoteUuids(mAddress); @@ -779,18 +788,19 @@ public final class BluetoothDevice implements Parcelable { } /** - * Perform a SDP query on the remote device to get the UUIDs - * supported. This API is asynchronous and an Intent is sent, - * with the UUIDs supported by the remote end. If there is an error - * in getting the SDP records or if the process takes a long time, - * an Intent is sent with the UUIDs that is currently present in the - * cache. Clients should use the {@link #getUuids} to get UUIDs - * is SDP is not to be performed. + * Perform a service discovery on the remote device to get the UUIDs supported. + * + * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent, + * with the UUIDs supported by the remote end. If there is an error + * in getting the SDP records or if the process takes a long time, + * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently + * present in the cache. Clients should use the {@link #getUuids} to get UUIDs + * if service discovery is not to be performed. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * - * @return False if the sanity check fails, True if the process + * @return False if the sanity check fails, True if the process * of initiating an ACL connection to the remote device * was started. - * @hide */ public boolean fetchUuidsWithSdp() { try { diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 5c6ef1a9eac8..36056529c3a6 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -165,6 +165,17 @@ public class NetworkStats implements Parcelable { dest.writeLongArray(operations); } + @Override + public NetworkStats clone() { + final NetworkStats clone = new NetworkStats(elapsedRealtime, size); + NetworkStats.Entry entry = null; + for (int i = 0; i < size; i++) { + entry = getValues(i, entry); + clone.addValues(entry); + } + return clone; + } + // @VisibleForTesting public NetworkStats addIfaceValues( String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) { @@ -455,7 +466,7 @@ public class NetworkStats implements Parcelable { public NetworkStats subtract(NetworkStats value) throws NonMonotonicException { final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime; if (deltaRealtime < 0) { - throw new IllegalArgumentException("found non-monotonic realtime"); + throw new NonMonotonicException(this, value); } // result will have our rows, and elapsed time between snapshots @@ -575,7 +586,8 @@ public class NetworkStats implements Parcelable { pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); for (int i = 0; i < size; i++) { pw.print(prefix); - pw.print(" iface="); pw.print(iface[i]); + pw.print(" ["); pw.print(i); pw.print("]"); + pw.print(" iface="); pw.print(iface[i]); pw.print(" uid="); pw.print(uid[i]); pw.print(" set="); pw.print(setToString(set[i])); pw.print(" tag="); pw.print(tagToString(tag[i])); @@ -638,6 +650,10 @@ public class NetworkStats implements Parcelable { public final int leftIndex; public final int rightIndex; + public NonMonotonicException(NetworkStats left, NetworkStats right) { + this(left, -1, right, -1); + } + public NonMonotonicException( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex) { this.left = checkNotNull(left, "missing left"); diff --git a/core/java/android/net/wimax/WimaxManagerConstants.java b/core/java/android/net/wimax/WimaxManagerConstants.java new file mode 100644 index 000000000000..b4aaf5bffe00 --- /dev/null +++ b/core/java/android/net/wimax/WimaxManagerConstants.java @@ -0,0 +1,104 @@ +package android.net.wimax; + +/** + * {@hide} + */ +public class WimaxManagerConstants +{ + + /** + * Used by android.net.wimax.WimaxManager for handling management of + * Wimax access. + */ + public static final String WIMAX_SERVICE = "WiMax"; + + /** + * Broadcast intent action indicating that Wimax has been enabled, disabled, + * enabling, disabling, or unknown. One extra provides this state as an int. + * Another extra provides the previous state, if available. + */ + public static final String NET_4G_STATE_CHANGED_ACTION = + "android.net.fourG.NET_4G_STATE_CHANGED"; + + /** + * The lookup key for an int that indicates whether Wimax is enabled, + * disabled, enabling, disabling, or unknown. + */ + public static final String EXTRA_WIMAX_STATUS = "wimax_status"; + + /** + * Broadcast intent action indicating that Wimax state has been changed + * state could be scanning, connecting, connected, disconnecting, disconnected + * initializing, initialized, unknown and ready. One extra provides this state as an int. + * Another extra provides the previous state, if available. + */ + public static final String WIMAX_NETWORK_STATE_CHANGED_ACTION = + "android.net.fourG.wimax.WIMAX_NETWORK_STATE_CHANGED"; + + /** + * Broadcast intent action indicating that Wimax signal level has been changed. + * Level varies from 0 to 3. + */ + public static final String SIGNAL_LEVEL_CHANGED_ACTION = + "android.net.wimax.SIGNAL_LEVEL_CHANGED"; + + /** + * The lookup key for an int that indicates whether Wimax state is + * scanning, connecting, connected, disconnecting, disconnected + * initializing, initialized, unknown and ready. + */ + public static final String EXTRA_WIMAX_STATE = "WimaxState"; + public static final String EXTRA_4G_STATE = "4g_state"; + public static final String EXTRA_WIMAX_STATE_INT = "WimaxStateInt"; + /** + * The lookup key for an int that indicates whether state of Wimax + * is idle. + */ + public static final String EXTRA_WIMAX_STATE_DETAIL = "WimaxStateDetail"; + + /** + * The lookup key for an int that indicates Wimax signal level. + */ + public static final String EXTRA_NEW_SIGNAL_LEVEL = "newSignalLevel"; + + /** + * Indicatates Wimax is disabled. + */ + public static final int NET_4G_STATE_DISABLED = 1; + + /** + * Indicatates Wimax is enabled. + */ + public static final int NET_4G_STATE_ENABLED = 3; + + /** + * Indicatates Wimax status is known. + */ + public static final int NET_4G_STATE_UNKNOWN = 4; + + /** + * Indicatates Wimax is in idle state. + */ + public static final int WIMAX_IDLE = 6; + + /** + * Indicatates Wimax is being deregistered. + */ + public static final int WIMAX_DEREGISTRATION = 8; + + /** + * Indicatates wimax state is unknown. + */ + public static final int WIMAX_STATE_UNKNOWN = 0; + + /** + * Indicatates wimax state is connected. + */ + public static final int WIMAX_STATE_CONNECTED = 7; + + /** + * Indicatates wimax state is disconnected. + */ + public static final int WIMAX_STATE_DISCONNECTED = 9; + +} diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index ff28596a207f..821b6df5fd15 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -1673,7 +1673,6 @@ public final class ContactsContract { * Querying for social stream data requires android.permission.READ_SOCIAL_STREAM * permission. * </p> - * @hide */ public static final class StreamItems implements StreamItemsColumns { /** @@ -2736,7 +2735,6 @@ public final class ContactsContract { * inserting or updating social stream items requires android.permission.WRITE_SOCIAL_STREAM * permission. * </p> - * @hide */ public static final class StreamItems implements BaseColumns, StreamItemsColumns { /** @@ -3149,7 +3147,6 @@ public final class ContactsContract { * </pre> * </dd> * </dl> - * @hide */ public static final class StreamItems implements BaseColumns, StreamItemsColumns { /** @@ -3247,7 +3244,6 @@ public final class ContactsContract { * Columns in the StreamItems table. * * @see ContactsContract.StreamItems - * @hide */ protected interface StreamItemsColumns { /** @@ -3538,7 +3534,6 @@ public final class ContactsContract { * <pre> * </dd> * </dl> - * @hide */ public static final class StreamItemPhotos implements BaseColumns, StreamItemPhotosColumns { /** @@ -3566,7 +3561,6 @@ public final class ContactsContract { * Columns in the StreamItemPhotos table. * * @see ContactsContract.StreamItemPhotos - * @hide */ protected interface StreamItemPhotosColumns { /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a0652f7c20d0..769776ecee92 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1183,6 +1183,10 @@ public final class Settings { public static final String RADIO_WIFI = "wifi"; /** + * {@hide} + */ + public static final String RADIO_WIMAX = "wimax"; + /** * Constant for use in AIRPLANE_MODE_RADIOS to specify Cellular radio. */ public static final String RADIO_CELL = "cell"; @@ -2899,6 +2903,11 @@ public final class Settings { */ public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on"; + /** + * {@hide} + */ + public static final String WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON = + "wimax_networks_available_notification_on"; /** * Delay (in seconds) before repeating the Wi-Fi networks available notification. @@ -4068,6 +4077,13 @@ public final class Settings { "contacts_preauth_uri_expiration"; /** + * Whether the Messaging app posts notifications. + * 0=disabled. 1=enabled. + */ + public static final String MESSAGING_APP_NOTIFICATIONS = "messaging_app_notifications"; + + + /** * This are the settings to be backed up. * * NOTE: Settings are backed up and restored in the order they appear @@ -4104,7 +4120,8 @@ public final class Settings { MOUNT_UMS_NOTIFY_ENABLED, UI_NIGHT_MODE, LOCK_SCREEN_OWNER_INFO, - LOCK_SCREEN_OWNER_INFO_ENABLED + LOCK_SCREEN_OWNER_INFO_ENABLED, + MESSAGING_APP_NOTIFICATIONS }; /** diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index 0e6d07d8dd18..8eb9da13d3fd 100755 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -1838,5 +1838,15 @@ public final class Telephony { public static final String EXTRA_PLMN = "plmn"; public static final String EXTRA_SHOW_SPN = "showSpn"; public static final String EXTRA_SPN = "spn"; + + /** + * Activity Action: Shows a dialog to turn off Messaging app notification. + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MESSAGING_APP_NOTIFICATIONS = + "android.provider.Telephony.MESSAGING_APP_NOTIFICATIONS"; + } } diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 5ee1b8a66067..8aafc3d078fe 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -16,14 +16,9 @@ package android.webkit; -import com.android.internal.widget.EditableInputConnection; - import android.content.Context; -import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.ColorFilter; import android.graphics.Paint; -import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; @@ -60,12 +55,12 @@ import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.TextView; +import junit.framework.Assert; + import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; -import junit.framework.Assert; - /** * WebTextView is a specialized version of EditText used by WebView * to overlay html textfields (and textareas) to use our standard @@ -926,18 +921,23 @@ import junit.framework.Assert; */ /* package */ void setRect(int x, int y, int width, int height) { LayoutParams lp = (LayoutParams) getLayoutParams(); + boolean needsUpdate = false; if (null == lp) { lp = new LayoutParams(width, height, x, y); } else { - lp.x = x; - lp.y = y; - lp.width = width; - lp.height = height; + if ((lp.x != x) || (lp.y != y) || (lp.width != width) + || (lp.height != height)) { + needsUpdate = true; + lp.x = x; + lp.y = y; + lp.width = width; + lp.height = height; + } } if (getParent() == null) { // Insert the view so that it's drawn first (at index 0) mWebView.addView(this, 0, lp); - } else { + } else if (needsUpdate) { setLayoutParams(lp); } // Set up a measure spec so a layout can always be recreated. diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 5ab99dcfa184..1a1b8d04365f 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -741,9 +741,16 @@ public class NumberPicker extends LinearLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMinWidth, mMaxWidth); - final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMinHeight, mMaxHeight); + // Try greedily to fit the max width and height. + final int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMaxWidth); + final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight); super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec); + // Flag if we are measured with width or height less than the respective min. + final int desiredWidth = Math.max(mMinWidth, getMeasuredWidth()); + final int desiredHeight = Math.max(mMinHeight, getMeasuredHeight()); + final int widthSize = resolveSizeAndState(desiredWidth, newWidthMeasureSpec, 0); + final int heightSize = resolveSizeAndState(desiredHeight, newHeightMeasureSpec, 0); + setMeasuredDimension(widthSize, heightSize); } @Override @@ -1357,23 +1364,19 @@ public class NumberPicker extends LinearLayout { * Makes a measure spec that tries greedily to use the max value. * * @param measureSpec The measure spec. - * @param maxValue The max value for the size. + * @param maxSize The max value for the size. * @return A measure spec greedily imposing the max size. */ - private int makeMeasureSpec(int measureSpec, int minValue, int maxValue) { + private int makeMeasureSpec(int measureSpec, int maxSize) { final int size = MeasureSpec.getSize(measureSpec); - if (size < minValue) { - throw new IllegalArgumentException("Available space is less than min size: " - + size + " < " + minValue); - } final int mode = MeasureSpec.getMode(measureSpec); switch (mode) { case MeasureSpec.EXACTLY: return measureSpec; case MeasureSpec.AT_MOST: - return MeasureSpec.makeMeasureSpec(Math.min(size, maxValue), MeasureSpec.EXACTLY); + return MeasureSpec.makeMeasureSpec(Math.min(size, maxSize), MeasureSpec.EXACTLY); case MeasureSpec.UNSPECIFIED: - return MeasureSpec.makeMeasureSpec(maxValue, MeasureSpec.EXACTLY); + return MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.EXACTLY); default: throw new IllegalArgumentException("Unknown measure mode: " + mode); } diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index e929e7d55b56..87c3e9bc8b25 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -82,6 +82,8 @@ public class SpellChecker implements SpellCheckerSessionListener { } private void setLocale(Locale locale) { + closeSession(); + final TextServicesManager textServicesManager = (TextServicesManager) mTextView.getContext().getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); if (!textServicesManager.isSpellCheckerEnabled()) { @@ -104,12 +106,6 @@ public class SpellChecker implements SpellCheckerSessionListener { // Change SpellParsers' wordIterator locale mWordIterator = new WordIterator(locale); - // Stop all SpellParsers - final int length = mSpellParsers.length; - for (int i = 0; i < length; i++) { - mSpellParsers[i].finish(); - } - // Remove existing misspelled SuggestionSpans mTextView.removeMisspelledSpans((Editable) mTextView.getText()); diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index 27d44bf9efe8..ec3790ec2710 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -68,6 +68,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { int mDropDownWidth; private int mGravity; + private boolean mDisableChildrenWhenDisabled; private Rect mTempRect = new Rect(); @@ -186,6 +187,9 @@ public class Spinner extends AbsSpinner implements OnClickListener { mPopup.setPromptText(a.getString(com.android.internal.R.styleable.Spinner_prompt)); + mDisableChildrenWhenDisabled = a.getBoolean( + com.android.internal.R.styleable.Spinner_disableChildrenWhenDisabled, false); + a.recycle(); // Base constructor can call setAdapter before we initialize mPopup. @@ -196,6 +200,17 @@ public class Spinner extends AbsSpinner implements OnClickListener { } } + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (mDisableChildrenWhenDisabled) { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + getChildAt(i).setEnabled(enabled); + } + } + } + /** * Describes how the selected item view is positioned. Currently only the horizontal component * is used. The default is determined by the current theme. @@ -398,6 +413,9 @@ public class Spinner extends AbsSpinner implements OnClickListener { addViewInLayout(child, 0, lp); child.setSelected(hasFocus()); + if (mDisableChildrenWhenDisabled) { + child.setEnabled(isEnabled()); + } // Get measure specs int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index d5450e4ab9bf..17b8acfd839f 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -439,17 +439,6 @@ public class LockPatternUtils { } /** - * Calls back SetupFaceLock to save the temporary gallery file if this is the backup lock. - * This doesn't have to verify that biometric is enabled because it's only called in that case - */ - void moveTempGallery() { - Intent intent = new Intent().setClassName("com.android.facelock", - "com.android.facelock.SetupFaceLock"); - intent.putExtra("moveTempGallery", true); - mContext.startActivity(intent); - } - - /** * Calls back SetupFaceLock to delete the temporary gallery file */ public void deleteTempGallery() { @@ -501,8 +490,7 @@ public class LockPatternUtils { setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); - setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true); - moveTempGallery(); + finishBiometricWeak(); } dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern .size(), 0, 0, 0, 0, 0, 0); @@ -619,8 +607,7 @@ public class LockPatternUtils { } else { setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality)); - setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true); - moveTempGallery(); + finishBiometricWeak(); } if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { int letters = 0; @@ -1087,4 +1074,16 @@ public class LockPatternUtils { } return false; } + + private void finishBiometricWeak() { + setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true); + + // Launch intent to show final screen, this also + // moves the temporary gallery to the actual gallery + Intent intent = new Intent(); + intent.setClassName("com.android.facelock", + "com.android.facelock.SetupEndScreen"); + mContext.startActivity(intent); + } + } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 18194ee0f298..230df39f0840 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -423,6 +423,12 @@ android:description="@string/permdesc_accessWifiState" android:label="@string/permlab_accessWifiState" /> + <!-- @hide --> + <permission android:name="android.permission.ACCESS_WIMAX_STATE" + android:permissionGroup="android.permission-group.NETWORK" + android:protectionLevel="normal" + android:description="@string/permdesc_accessWimaxState" + android:label="@string/permlab_accessWimaxState" /> <!-- Allows applications to connect to paired bluetooth devices --> <permission android:name="android.permission.BLUETOOTH" android:permissionGroup="android.permission-group.NETWORK" @@ -984,6 +990,12 @@ android:description="@string/permdesc_changeWifiState" android:label="@string/permlab_changeWifiState" /> + <!-- @hide --> + <permission android:name="android.permission.CHANGE_WIMAX_STATE" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="dangerous" + android:description="@string/permdesc_changeWimaxState" + android:label="@string/permlab_changeWimaxState" /> <!-- Allows applications to enter Wi-Fi Multicast mode --> <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" @@ -1015,6 +1027,13 @@ android:label="@string/permlab_readLogs" android:description="@string/permdesc_readLogs" /> + <!-- Allows an application to use any media decoder when decoding for playback + @hide --> + <permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK" + android:protectionLevel="signatureOrSystem" + android:label="@string/permlab_anyCodecForPlayback" + android:description="@string/permdesc_anyCodecForPlayback" /> + <!-- ========================================= --> <!-- Permissions for special development tools --> <!-- ========================================= --> diff --git a/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differnew file mode 100644 index 000000000000..c2e4b783c31e --- /dev/null +++ b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png diff --git a/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differnew file mode 100644 index 000000000000..51b839fd5572 --- /dev/null +++ b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png diff --git a/core/res/res/layout/action_menu_layout.xml b/core/res/res/layout/action_menu_layout.xml index 5696d87de813..c401fec8840d 100644 --- a/core/res/res/layout/action_menu_layout.xml +++ b/core/res/res/layout/action_menu_layout.xml @@ -18,6 +18,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:divider="?android:attr/dividerVertical" + android:divider="?android:attr/actionBarDivider" android:dividerPadding="12dip" android:gravity="center_vertical" /> diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml index 551c1d844157..5b488c08e0ea 100644 --- a/core/res/res/values-sw600dp/dimens.xml +++ b/core/res/res/values-sw600dp/dimens.xml @@ -60,6 +60,12 @@ <!-- Compensate for double margin : preference_screen_side_margin + 4 (frame background shadow) = -preference_screen_side_margin_negative --> <dimen name="preference_screen_side_margin_negative">-4dp</dimen> + <!-- Default padding to apply to AppWidgetHostViews containing widgets targeting API level 14 and up. --> + <dimen name="default_app_widget_padding_left">12dp</dimen> + <dimen name="default_app_widget_padding_top">12dp</dimen> + <dimen name="default_app_widget_padding_right">4dp</dimen> + <dimen name="default_app_widget_padding_bottom">20dp</dimen> + <!-- Minimum width for an action button in the menu area of an action bar --> <dimen name="action_button_min_width">64dip</dimen> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index a40e24c0b147..d0ab8b116d06 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3331,6 +3331,9 @@ <attr name="popupPromptView" format="reference" /> <!-- Gravity setting for positioning the currently selected item. --> <attr name="gravity" /> + <!-- Whether this spinner should mark child views as enabled/disabled when + the spinner itself is enabled/disabled. --> + <attr name="disableChildrenWhenDisabled" format="boolean" /> </declare-styleable> <declare-styleable name="DatePicker"> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 48e8f1eb70eb..8b07e347184b 100755..100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -166,6 +166,12 @@ </string-array> <!-- List of regexpressions describing the interface (if any) that represent tetherable + WiMAX interfaces. If the device doesn't want to support tethering over Wifi this + should be empty. An example would be "softap.*" --> + <string-array translatable="false" name="config_tether_wimax_regexs"> + </string-array> + + <!-- List of regexpressions describing the interface (if any) that represent tetherable bluetooth interfaces. If the device doesn't want to support tethering over bluetooth this should be empty. --> <string-array translatable="false" name="config_tether_bluetooth_regexs"> @@ -718,4 +724,16 @@ <!-- Default network policy warning threshold, in megabytes. --> <integer name="config_networkPolicyDefaultWarning">2048</integer> + <!-- Set and Unsets WiMAX --> + <bool name="config_wimaxEnabled">false</bool> + <!-- Location of the wimax framwork jar location --> + <string name="config_wimaxServiceJarLocation"></string> + <!-- Location of the wimax native library locaiton --> + <string name="config_wimaxNativeLibLocation"></string> + <!-- Name of the wimax manager class --> + <string name="config_wimaxManagerClassname"></string> + <!-- Name of the wimax service class --> + <string name="config_wimaxServiceClassname"></string> + <!-- Name of the wimax state tracker clas --> + <string name="config_wimaxStateTrackerClassname"></string> </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 97d5afe8cfdf..4d97ad20f4a5 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1974,5 +1974,4 @@ <public type="color" name="holo_orange_dark" id="0x01060019" /> <public type="color" name="holo_purple" id="0x0106001a" /> <public type="color" name="holo_blue_bright" id="0x0106001b" /> - </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index a81917342180..9b8be854e325 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -831,6 +831,12 @@ including personal or private information.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_anyCodecForPlayback">use any media decoder for playback</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_anyCodecForPlayback">Allows an application to use any installed + media decoder to decode for playback.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_diagnostic">read/write to resources owned by diag</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_diagnostic">Allows an application to read and write to @@ -1362,6 +1368,12 @@ than the non-multicast mode.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_accessWimaxState">view WiMAX state</string> + <string name="permdesc_accessWimaxState">Allows an application to view + the information about the state of WiMAX.</string> + <string name="permlab_changeWimaxState">change WiMAX state</string> + <string name="permdesc_changeWimaxState">Allows an application to connect + to and disconnect from WiMAX network.</string> <string name="permlab_bluetoothAdmin">bluetooth administration</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_bluetoothAdmin" product="tablet">Allows an application to configure diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 949f01f910b3..73e1a7c0303e 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1798,6 +1798,7 @@ please see styles_device_defaults.xml. <item name="android:dropDownWidth">wrap_content</item> <item name="android:popupPromptView">@android:layout/simple_dropdown_hint</item> <item name="android:gravity">left|center_vertical</item> + <item name="android:disableChildrenWhenDisabled">true</item> </style> <style name="Widget.Holo.Spinner.DropDown"> diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index b37eb466e1ca..098464f9f013 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -294,6 +294,22 @@ public class NetworkStatsTest extends TestCase { assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L); } + public void testClone() throws Exception { + final NetworkStats original = new NetworkStats(TEST_START, 5) + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L); + + // make clone and mutate original + final NetworkStats clone = original.clone(); + original.addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L); + + assertEquals(3, original.size()); + assertEquals(2, clone.size()); + + assertEquals(128L + 512L + 128L, original.getTotalBytes()); + assertEquals(128L + 512L, clone.getTotalBytes()); + } + private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { final NetworkStats.Entry entry = stats.getValues(index, null); diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index f3b62ec10e51..29fab11603a4 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -130,10 +130,17 @@ public class SurfaceTexture { } /** - * Set the size of buffers returned by requestBuffers when a width and height - * of zero is requested. + * Set the default size of the image buffers. The image producer may override the buffer size, + * in which case the producer-set buffer size will be used, not the default size set by this + * method. Both video and camera based image producers do override the size. This method may + * be used to set the image size when producing images with {@link android.graphics.Canvas} (via + * {@link android.view.Surface#lockCanvas}), or OpenGL ES (via an EGLSurface). * - * @hide Pending approval by API council. + * The new default buffer size will take effect the next time the image producer requests a + * buffer to fill. For {@link android.graphics.Canvas} this will be the next time {@link + * android.view.Surface#lockCanvas} is called. For OpenGL ES, the EGLSurface should be + * destroyed (via eglDestroySurface), made not-current (via eglMakeCurrent), and then recreated + * (via eglCreateWindowSurface) to ensure that the new default size has taken effect. */ public void setDefaultBufferSize(int width, int height) { nativeSetDefaultBufferSize(width, height); diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h index 0e2cdf79ad19..e9059031fbfa 100644 --- a/include/media/IMediaPlayer.h +++ b/include/media/IMediaPlayer.h @@ -40,7 +40,6 @@ public: const KeyedVector<String8, String8>* headers) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; virtual status_t setDataSource(const sp<IStreamSource>& source) = 0; - virtual status_t setVideoSurface(const sp<Surface>& surface) = 0; virtual status_t setVideoSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) = 0; virtual status_t prepareAsync() = 0; diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 4328d3cc6d74..80f43a342a55 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -117,9 +117,6 @@ public: return INVALID_OPERATION; } - // pass the buffered Surface to the media player service - virtual status_t setVideoSurface(const sp<Surface>& surface) = 0; - // pass the buffered ISurfaceTexture to the media player service virtual status_t setVideoSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) = 0; diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 08835fb6c6b9..e6a0cc569b46 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -170,7 +170,6 @@ public: status_t setDataSource(int fd, int64_t offset, int64_t length); status_t setDataSource(const sp<IStreamSource> &source); - status_t setVideoSurface(const sp<Surface>& surface); status_t setVideoSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture); status_t setListener(const sp<MediaPlayerListener>& listener); diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index 50a41ca153ee..9c1e6b727b38 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -35,7 +35,6 @@ enum { SET_DATA_SOURCE_URL, SET_DATA_SOURCE_FD, SET_DATA_SOURCE_STREAM, - SET_VIDEO_SURFACE, PREPARE_ASYNC, START, STOP, @@ -112,16 +111,6 @@ public: return reply.readInt32(); } - // pass the buffered Surface to the media player service - status_t setVideoSurface(const sp<Surface>& surface) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - Surface::writeToParcel(surface, &data); - remote()->transact(SET_VIDEO_SURFACE, data, &reply); - return reply.readInt32(); - } - // pass the buffered ISurfaceTexture to the media player service status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture) { @@ -345,12 +334,6 @@ status_t BnMediaPlayer::onTransact( reply->writeInt32(setDataSource(source)); return NO_ERROR; } - case SET_VIDEO_SURFACE: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - sp<Surface> surface = Surface::readFromParcel(data); - reply->writeInt32(setVideoSurface(surface)); - return NO_ERROR; - } break; case SET_VIDEO_SURFACETEXTURE: { CHECK_INTERFACE(IMediaPlayer, data, reply); sp<ISurfaceTexture> surfaceTexture = diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index f72300beca1f..c2e1ddfaf43b 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -219,14 +219,6 @@ status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *m return mPlayer->getMetadata(update_only, apply_filter, metadata); } -status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) -{ - LOGV("setVideoSurface"); - Mutex::Autolock _l(mLock); - if (mPlayer == 0) return NO_INIT; - return mPlayer->setVideoSurface(surface); -} - status_t MediaPlayer::setVideoSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) { diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index b6553586c9fa..e8d0f0c14075 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -788,14 +788,6 @@ status_t MediaPlayerService::Client::setDataSource( return mStatus; } -status_t MediaPlayerService::Client::setVideoSurface(const sp<Surface>& surface) -{ - LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get()); - sp<MediaPlayerBase> p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - return p->setVideoSurface(surface); -} - void MediaPlayerService::Client::disconnectNativeWindow() { if (mConnectedWindow != NULL) { status_t err = native_window_api_disconnect(mConnectedWindow.get(), diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 62214bab2250..04d9e28e1199 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -248,7 +248,6 @@ private: // IMediaPlayer interface virtual void disconnect(); - virtual status_t setVideoSurface(const sp<Surface>& surface); virtual status_t setVideoSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture); virtual status_t prepareAsync(); diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index b35696f1204c..34693898700c 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -35,7 +35,6 @@ public: const char* path, const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp<Surface>& surface) { return UNKNOWN_ERROR; } virtual status_t setVideoSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) { return UNKNOWN_ERROR; } diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index cd4b1efffcbc..598d573c13d6 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -69,12 +69,6 @@ status_t StagefrightPlayer::setDataSource(const sp<IStreamSource> &source) { return mPlayer->setDataSource(source); } -status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) { - LOGV("setVideoSurface"); - - return mPlayer->setSurface(surface); -} - status_t StagefrightPlayer::setVideoSurfaceTexture( const sp<ISurfaceTexture> &surfaceTexture) { LOGV("setVideoSurfaceTexture"); diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h index cbc6d4996da1..e89e18ab2b63 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -40,7 +40,6 @@ public: virtual status_t setDataSource(const sp<IStreamSource> &source); - virtual status_t setVideoSurface(const sp<Surface> &surface); virtual status_t setVideoSurfaceTexture( const sp<ISurfaceTexture> &surfaceTexture); virtual status_t prepare(); diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h index 802a11b0eff3..91ffa7dc43fe 100644 --- a/media/libmediaplayerservice/TestPlayerStub.h +++ b/media/libmediaplayerservice/TestPlayerStub.h @@ -75,9 +75,6 @@ class TestPlayerStub : public MediaPlayerInterface { // All the methods below wrap the mPlayer instance. - virtual status_t setVideoSurface(const android::sp<android::Surface>& s) { - return mPlayer->setVideoSurface(s); - } virtual status_t setVideoSurfaceTexture( const android::sp<android::ISurfaceTexture>& st) { return mPlayer->setVideoSurfaceTexture(st); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 70208f8a6136..2a5c0a6c53c6 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -99,12 +99,6 @@ void NuPlayer::setDataSource( msg->post(); } -void NuPlayer::setVideoSurface(const sp<Surface> &surface) { - sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); - msg->setObject("native-window", new NativeWindowWrapper(surface)); - msg->post(); -} - void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ? diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index f90759dd3e94..f23deea60765 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -42,7 +42,6 @@ struct NuPlayer : public AHandler { void setDataSource( const char *url, const KeyedVector<String8, String8> *headers); - void setVideoSurface(const sp<Surface> &surface); void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink); void start(); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 452ba994abd6..5aa99bfa1ead 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -89,12 +89,6 @@ status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) { return OK; } -status_t NuPlayerDriver::setVideoSurface(const sp<Surface> &surface) { - mPlayer->setVideoSurface(surface); - - return OK; -} - status_t NuPlayerDriver::setVideoSurfaceTexture( const sp<ISurfaceTexture> &surfaceTexture) { mPlayer->setVideoSurfaceTexture(surfaceTexture); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h index aaa3de0f0d9c..4a0026ca90ad 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h @@ -37,7 +37,6 @@ struct NuPlayerDriver : public MediaPlayerInterface { virtual status_t setDataSource(const sp<IStreamSource> &source); - virtual status_t setVideoSurface(const sp<Surface> &surface); virtual status_t setVideoSurfaceTexture( const sp<ISurfaceTexture> &surfaceTexture); virtual status_t prepare(); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index bf19040fbeb3..640e9fac9c07 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -381,7 +381,7 @@ void NuPlayer::Renderer::onDrainVideoQueue() { LOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6); } - entry->mNotifyConsumed->setInt32("render", true); + entry->mNotifyConsumed->setInt32("render", !tooLate); entry->mNotifyConsumed->post(); mVideoQueue.erase(mVideoQueue.begin()); entry = NULL; diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index f37e75baa758..7d9d7ed9aa6a 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -1139,18 +1139,9 @@ bool AwesomePlayer::isPlaying() const { return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); } -status_t AwesomePlayer::setSurface(const sp<Surface> &surface) { - Mutex::Autolock autoLock(mLock); - - mSurface = surface; - return setNativeWindow_l(surface); -} - status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { Mutex::Autolock autoLock(mLock); - mSurface.clear(); - status_t err; if (surfaceTexture != NULL) { err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture)); diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 7d6bcad4df01..c13d6cba98d7 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -81,7 +81,6 @@ struct AwesomePlayer { bool isPlaying() const; - status_t setSurface(const sp<Surface> &surface); status_t setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink); status_t setLooping(bool shouldLoop); @@ -154,7 +153,6 @@ private: bool mUIDValid; uid_t mUID; - sp<Surface> mSurface; sp<ANativeWindow> mNativeWindow; sp<MediaPlayerBase::AudioSink> mAudioSink; diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp index ed3051bf44a2..a6fdeea5684b 100644 --- a/media/tests/players/invoke_mock_media_player.cpp +++ b/media/tests/players/invoke_mock_media_player.cpp @@ -68,7 +68,6 @@ class Player: public MediaPlayerBase } virtual status_t setDataSource(int fd, int64_t offset, int64_t length) {return OK;} - virtual status_t setVideoSurface(const sp<Surface>& surface) {return OK;} virtual status_t setVideoSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) {return OK;} virtual status_t prepare() {return OK;} diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index a08932a3dd64..8e8e26c0a849 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -256,6 +256,21 @@ typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)(void); typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void); #endif + +/* EGL_ANDROID_blob_cache + */ +#ifndef EGL_ANDROID_blob_cache +#define EGL_ANDROID_blob_cache 1 +typedef khronos_ssize_t EGLsizei; +typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, const void* value, EGLsizei valueSize); +typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, void* value, EGLsizei valueSize); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncs(EGLDisplay dpy, EGLSetBlobFunc set, EGLGetBlobFunc get); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy, + EGLSetBlobFunc set, EGLGetBlobFunc get); +#endif + #ifdef __cplusplus } #endif diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp index 1e64302f26a9..aa40d5888ce5 100644 --- a/opengl/libs/EGL/egl_cache.cpp +++ b/opengl/libs/EGL/egl_cache.cpp @@ -19,6 +19,21 @@ #include "egl_impl.h" #include "egldefs.h" +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +// Cache size limits. +static const size_t maxKeySize = 1024; +static const size_t maxValueSize = 4096; +static const size_t maxTotalSize = 64 * 1024; + +// Cache file header +static const char* cacheFileMagic = "EGL$"; +static const size_t cacheFileHeaderSize = 8; + // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- @@ -26,37 +41,37 @@ namespace android { #define BC_EXT_STR "EGL_ANDROID_blob_cache" // -// EGL_ANDROID_blob_cache types and functions +// Callback functions passed to EGL. // -typedef khronos_ssize_t EGLsizei; - -typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, - const void* value, EGLsizei valueSize); - -typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, - void* value, EGLsizei valueSize); +static void setBlob(const void* key, EGLsizei keySize, const void* value, + EGLsizei valueSize) { + egl_cache_t::get()->setBlob(key, keySize, value, valueSize); +} -typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy, - EGLSetBlobFunc set, EGLGetBlobFunc get); +static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value, + EGLsizei valueSize) { + return egl_cache_t::get()->getBlob(key, keySize, value, valueSize); +} // // egl_cache_t definition // -static void setBlob(const void* key, EGLsizei keySize, const void* value, - EGLsizei valueSize) { +egl_cache_t::egl_cache_t() : + mInitialized(false), + mBlobCache(NULL) { } -static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value, - EGLsizei valueSize) { - return 0; +egl_cache_t::~egl_cache_t() { } +egl_cache_t egl_cache_t::sCache; + egl_cache_t* egl_cache_t::get() { - static egl_cache_t theCache; - return &theCache; + return &sCache; } void egl_cache_t::initialize(egl_display_t *display) { + Mutex::Autolock lock(mMutex); for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) { @@ -79,7 +94,8 @@ void egl_cache_t::initialize(egl_display_t *display) { continue; } - eglSetBlobCacheFuncs(display->disp[i].dpy, setBlob, getBlob); + eglSetBlobCacheFuncs(display->disp[i].dpy, android::setBlob, + android::getBlob); EGLint err = cnx->egl.eglGetError(); if (err != EGL_SUCCESS) { LOGE("eglSetBlobCacheFuncs resulted in an error: %#x", @@ -88,6 +104,210 @@ void egl_cache_t::initialize(egl_display_t *display) { } } } + mInitialized = true; +} + +void egl_cache_t::terminate() { + Mutex::Autolock lock(mMutex); + if (mBlobCache != NULL) { + saveBlobCacheLocked(); + mBlobCache = NULL; + } + mInitialized = false; +} + +void egl_cache_t::setBlob(const void* key, EGLsizei keySize, const void* value, + EGLsizei valueSize) { + Mutex::Autolock lock(mMutex); + + if (keySize < 0 || valueSize < 0) { + LOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed"); + return; + } + + if (mInitialized) { + sp<BlobCache> bc = getBlobCacheLocked(); + bc->set(key, keySize, value, valueSize); + } +} + +EGLsizei egl_cache_t::getBlob(const void* key, EGLsizei keySize, void* value, + EGLsizei valueSize) { + Mutex::Autolock lock(mMutex); + + if (keySize < 0 || valueSize < 0) { + LOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed"); + return 0; + } + + if (mInitialized) { + sp<BlobCache> bc = getBlobCacheLocked(); + return bc->get(key, keySize, value, valueSize); + } + return 0; +} + +void egl_cache_t::setCacheFilename(const char* filename) { + Mutex::Autolock lock(mMutex); + mFilename = filename; +} + +sp<BlobCache> egl_cache_t::getBlobCacheLocked() { + if (mBlobCache == NULL) { + mBlobCache = new BlobCache(maxKeySize, maxValueSize, maxTotalSize); + loadBlobCacheLocked(); + } + return mBlobCache; +} + +static uint32_t crc32c(const uint8_t* buf, size_t len) { + const uint32_t polyBits = 0x82F63B78; + uint32_t r = 0; + for (size_t i = 0; i < len; i++) { + r ^= buf[i]; + for (int j = 0; j < 8; j++) { + if (r & 1) { + r = (r >> 1) ^ polyBits; + } else { + r >>= 1; + } + } + } + return r; +} + +void egl_cache_t::saveBlobCacheLocked() { + if (mFilename.length() > 0) { + size_t cacheSize = mBlobCache->getFlattenedSize(); + size_t headerSize = cacheFileHeaderSize; + const char* fname = mFilename.string(); + + // Try to create the file with no permissions so we can write it + // without anyone trying to read it. + int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0); + if (fd == -1) { + if (errno == EEXIST) { + // The file exists, delete it and try again. + if (unlink(fname) == -1) { + // No point in retrying if the unlink failed. + LOGE("error unlinking cache file %s: %s (%d)", fname, + strerror(errno), errno); + return; + } + // Retry now that we've unlinked the file. + fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0); + } + if (fd == -1) { + LOGE("error creating cache file %s: %s (%d)", fname, + strerror(errno), errno); + return; + } + } + + size_t fileSize = headerSize + cacheSize; + if (ftruncate(fd, fileSize) == -1) { + LOGE("error setting cache file size: %s (%d)", strerror(errno), + errno); + close(fd); + unlink(fname); + return; + } + + uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize, + PROT_WRITE, MAP_SHARED, fd, 0)); + if (buf == MAP_FAILED) { + LOGE("error mmaping cache file: %s (%d)", strerror(errno), + errno); + close(fd); + unlink(fname); + return; + } + + status_t err = mBlobCache->flatten(buf + headerSize, cacheSize, NULL, + 0); + if (err != OK) { + LOGE("error writing cache contents: %s (%d)", strerror(-err), + -err); + munmap(buf, fileSize); + close(fd); + unlink(fname); + return; + } + + // Write the file magic and CRC + memcpy(buf, cacheFileMagic, 4); + uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4); + *crc = crc32c(buf + headerSize, cacheSize); + + munmap(buf, fileSize); + fchmod(fd, S_IRUSR); + close(fd); + } +} + +void egl_cache_t::loadBlobCacheLocked() { + if (mFilename.length() > 0) { + size_t headerSize = cacheFileHeaderSize; + + int fd = open(mFilename.string(), O_RDONLY, 0); + if (fd == -1) { + if (errno != ENOENT) { + LOGE("error opening cache file %s: %s (%d)", mFilename.string(), + strerror(errno), errno); + } + return; + } + + struct stat statBuf; + if (fstat(fd, &statBuf) == -1) { + LOGE("error stat'ing cache file: %s (%d)", strerror(errno), errno); + close(fd); + return; + } + + // Sanity check the size before trying to mmap it. + size_t fileSize = statBuf.st_size; + if (fileSize > maxTotalSize * 2) { + LOGE("cache file is too large: %#llx", statBuf.st_size); + close(fd); + return; + } + + uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize, + PROT_READ, MAP_PRIVATE, fd, 0)); + if (buf == MAP_FAILED) { + LOGE("error mmaping cache file: %s (%d)", strerror(errno), + errno); + close(fd); + return; + } + + // Check the file magic and CRC + size_t cacheSize = fileSize - headerSize; + if (memcmp(buf, cacheFileMagic, 4) != 0) { + LOGE("cache file has bad mojo"); + close(fd); + return; + } + uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4); + if (crc32c(buf + headerSize, cacheSize) != *crc) { + LOGE("cache file failed CRC check"); + close(fd); + return; + } + + status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL, 0); + if (err != OK) { + LOGE("error reading cache contents: %s (%d)", strerror(-err), + -err); + munmap(buf, fileSize); + close(fd); + return; + } + + munmap(buf, fileSize); + close(fd); + } } // ---------------------------------------------------------------------------- diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h index 1fcfaccd8509..05d5873181e5 100644 --- a/opengl/libs/EGL/egl_cache.h +++ b/opengl/libs/EGL/egl_cache.h @@ -14,20 +14,110 @@ ** limitations under the License. */ +#ifndef ANDROID_EGL_CACHE_H +#define ANDROID_EGL_CACHE_H + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <utils/BlobCache.h> +#include <utils/String8.h> +#include <utils/StrongPointer.h> + // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- class egl_display_t; -class egl_cache_t { +class EGLAPI egl_cache_t { public: + // get returns a pointer to the singleton egl_cache_t object. This + // singleton object will never be destroyed. static egl_cache_t* get(); + // initialize puts the egl_cache_t into an initialized state, such that it + // is able to insert and retrieve entries from the cache. This should be + // called when EGL is initialized. When not in the initialized state the + // getBlob and setBlob methods will return without performing any cache + // operations. void initialize(egl_display_t* display); + + // terminate puts the egl_cache_t back into the uninitialized state. When + // in this state the getBlob and setBlob methods will return without + // performing any cache operations. + void terminate(); + + // setBlob attempts to insert a new key/value blob pair into the cache. + // This will be called by the hardware vendor's EGL implementation via the + // EGL_ANDROID_blob_cache extension. + void setBlob(const void* key, EGLsizei keySize, const void* value, + EGLsizei valueSize); + + // getBlob attempts to retrieve the value blob associated with a given key + // blob from cache. This will be called by the hardware vendor's EGL + // implementation via the EGL_ANDROID_blob_cache extension. + EGLsizei getBlob(const void* key, EGLsizei keySize, void* value, + EGLsizei valueSize); + + // setCacheFilename sets the name of the file that should be used to store + // cache contents from one program invocation to another. + void setCacheFilename(const char* filename); + +private: + // Creation and (the lack of) destruction is handled internally. + egl_cache_t(); + ~egl_cache_t(); + + // Copying is disallowed. + egl_cache_t(const egl_cache_t&); // not implemented + void operator=(const egl_cache_t&); // not implemented + + // getBlobCacheLocked returns the BlobCache object being used to store the + // key/value blob pairs. If the BlobCache object has not yet been created, + // this will do so, loading the serialized cache contents from disk if + // possible. + sp<BlobCache> getBlobCacheLocked(); + + // saveBlobCache attempts to save the current contents of mBlobCache to + // disk. + void saveBlobCacheLocked(); + + // loadBlobCache attempts to load the saved cache contents from disk into + // mBlobCache. + void loadBlobCacheLocked(); + + // mInitialized indicates whether the egl_cache_t is in the initialized + // state. It is initialized to false at construction time, and gets set to + // true when initialize is called. It is set back to false when terminate + // is called. When in this state, the cache behaves as normal. When not, + // the getBlob and setBlob methods will return without performing any cache + // operations. + bool mInitialized; + + // mBlobCache is the cache in which the key/value blob pairs are stored. It + // is initially NULL, and will be initialized by getBlobCacheLocked the + // first time it's needed. + sp<BlobCache> mBlobCache; + + // mFilename is the name of the file for storing cache contents in between + // program invocations. It is initialized to an empty string at + // construction time, and can be set with the setCacheFilename method. An + // empty string indicates that the cache should not be saved to or restored + // from disk. + String8 mFilename; + + // mMutex is the mutex used to prevent concurrent access to the member + // variables. It must be locked whenever the member variables are accessed. + mutable Mutex mMutex; + + // sCache is the singleton egl_cache_t object. + static egl_cache_t sCache; }; // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- + +#endif // ANDROID_EGL_CACHE_H diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 0f92864635c8..558ca77ff994 100644 --- a/opengl/libs/EGL/egl_display.cpp +++ b/opengl/libs/EGL/egl_display.cpp @@ -44,6 +44,7 @@ egl_display_t::egl_display_t() : egl_display_t::~egl_display_t() { magic = 0; + egl_cache_t::get()->terminate(); } egl_display_t* egl_display_t::get(EGLDisplay dpy) { diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h index 113595f17907..1c1092cd428d 100644 --- a/opengl/libs/EGL/egl_display.h +++ b/opengl/libs/EGL/egl_display.h @@ -59,7 +59,7 @@ struct egl_config_t { // ---------------------------------------------------------------------------- -class egl_display_t { +class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes static egl_display_t sDisplay[NUM_DISPLAYS]; EGLDisplay getDisplay(EGLNativeDisplayType display); @@ -141,4 +141,3 @@ EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface); // ---------------------------------------------------------------------------- #endif // ANDROID_EGL_DISPLAY_H - diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk index 92d7eb12ac9d..14104d171ee0 100644 --- a/opengl/tests/EGLTest/Android.mk +++ b/opengl/tests/EGLTest/Android.mk @@ -7,6 +7,7 @@ LOCAL_MODULE := EGL_test LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := \ + egl_cache_test.cpp \ EGL_test.cpp \ LOCAL_SHARED_LIBRARIES := \ @@ -21,9 +22,12 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_C_INCLUDES := \ bionic \ + bionic/libc/private \ bionic/libstdc++/include \ external/gtest/include \ external/stlport/stlport \ + frameworks/base/opengl/libs \ + frameworks/base/opengl/libs/EGL \ include $(BUILD_EXECUTABLE) diff --git a/opengl/tests/EGLTest/egl_cache_test.cpp b/opengl/tests/EGLTest/egl_cache_test.cpp new file mode 100644 index 000000000000..c7d9e3e201dc --- /dev/null +++ b/opengl/tests/EGLTest/egl_cache_test.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "EGL_test" +//#define LOG_NDEBUG 0 + +#include <gtest/gtest.h> + +#include <utils/Log.h> + +#include "egl_cache.h" +#include "egl_display.h" + +namespace android { + +class EGLCacheTest : public ::testing::Test { +protected: + virtual void SetUp() { + mCache = egl_cache_t::get(); + } + + virtual void TearDown() { + mCache->setCacheFilename(""); + mCache->terminate(); + } + + egl_cache_t* mCache; +}; + +TEST_F(EGLCacheTest, UninitializedCacheAlwaysMisses) { + char buf[4] = { 0xee, 0xee, 0xee, 0xee }; + mCache->setBlob("abcd", 4, "efgh", 4); + ASSERT_EQ(0, mCache->getBlob("abcd", 4, buf, 4)); + ASSERT_EQ(0xee, buf[0]); + ASSERT_EQ(0xee, buf[1]); + ASSERT_EQ(0xee, buf[2]); + ASSERT_EQ(0xee, buf[3]); +} + +TEST_F(EGLCacheTest, InitializedCacheAlwaysHits) { + char buf[4] = { 0xee, 0xee, 0xee, 0xee }; + mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY)); + mCache->setBlob("abcd", 4, "efgh", 4); + ASSERT_EQ(4, mCache->getBlob("abcd", 4, buf, 4)); + ASSERT_EQ('e', buf[0]); + ASSERT_EQ('f', buf[1]); + ASSERT_EQ('g', buf[2]); + ASSERT_EQ('h', buf[3]); +} + +TEST_F(EGLCacheTest, TerminatedCacheAlwaysMisses) { + char buf[4] = { 0xee, 0xee, 0xee, 0xee }; + mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY)); + mCache->setBlob("abcd", 4, "efgh", 4); + mCache->terminate(); + ASSERT_EQ(0, mCache->getBlob("abcd", 4, buf, 4)); + ASSERT_EQ(0xee, buf[0]); + ASSERT_EQ(0xee, buf[1]); + ASSERT_EQ(0xee, buf[2]); + ASSERT_EQ(0xee, buf[3]); +} + +class EGLCacheSerializationTest : public EGLCacheTest { + +protected: + + virtual void SetUp() { + EGLCacheTest::SetUp(); + + char* tn = tempnam("/sdcard", "EGL_test-cache-"); + mFilename = tn; + free(tn); + } + + virtual void TearDown() { + unlink(mFilename.string()); + EGLCacheTest::TearDown(); + } + + String8 mFilename; +}; + +TEST_F(EGLCacheSerializationTest, ReinitializedCacheContainsValues) { + char buf[4] = { 0xee, 0xee, 0xee, 0xee }; + mCache->setCacheFilename(mFilename); + mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY)); + mCache->setBlob("abcd", 4, "efgh", 4); + mCache->terminate(); + mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY)); + ASSERT_EQ(4, mCache->getBlob("abcd", 4, buf, 4)); + ASSERT_EQ('e', buf[0]); + ASSERT_EQ('f', buf[1]); + ASSERT_EQ('g', buf[2]); + ASSERT_EQ('h', buf[3]); +} + +} diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 3920257a7c43..0891525829ef 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -21,7 +21,7 @@ <integer name="def_screen_off_timeout">60000</integer> <bool name="def_airplane_mode_on">false</bool> <!-- Comma-separated list of bluetooth, wifi, and cell. --> - <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi,nfc</string> + <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi,nfc,wimax</string> <string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi,nfc</string> <bool name="def_auto_time">true</bool> <bool name="def_auto_time_zone">true</bool> @@ -133,4 +133,8 @@ <bool name="def_dtmf_tones_enabled">true</bool> <!-- Default for UI touch sounds enabled --> <bool name="def_sound_effects_enabled">true</bool> + + <!-- Default for Messaging app notifications enabled --> + <bool name="def_messaging_app_notifications_on">true</bool> + </resources> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 5495d0840477..44194f033f48 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -1472,6 +1472,10 @@ public class DatabaseHelper extends SQLiteOpenHelper { loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED, R.bool.def_touch_exploration_enabled); + + loadBooleanSetting(stmt, Settings.Secure.MESSAGING_APP_NOTIFICATIONS, + R.bool.def_messaging_app_notifications_on); + } finally { if (stmt != null) stmt.close(); } diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png Binary files differnew file mode 100644 index 000000000000..f24d8016fca9 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differnew file mode 100644 index 000000000000..66eb5db188d2 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png Binary files differnew file mode 100644 index 000000000000..edff74a46275 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differnew file mode 100644 index 000000000000..1cdd4eb5fbf0 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png Binary files differnew file mode 100644 index 000000000000..95fdaf9e6f21 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differnew file mode 100644 index 000000000000..8678e39f8d6a --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png Binary files differnew file mode 100644 index 000000000000..1d2d2901acf3 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differnew file mode 100644 index 000000000000..c2e4b783c31e --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differnew file mode 100644 index 000000000000..51b839fd5572 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png Binary files differnew file mode 100644 index 000000000000..b20c5c78ef4c --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml index eb644b3630b3..93ac22ed0920 100644 --- a/packages/SystemUI/res/layout/signal_cluster_view.xml +++ b/packages/SystemUI/res/layout/signal_cluster_view.xml @@ -52,6 +52,27 @@ android:id="@+id/spacer" /> <FrameLayout + android:id="@+id/wimax_combo" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_marginRight="-6dp" + > + <ImageView + android:id="@+id/wimax_signal" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + android:scaleType="center" + /> + <ImageView + android:id="@+id/wimax_inout" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_gravity="center|bottom" + /> + </FrameLayout> + <FrameLayout android:layout_height="wrap_content" android:layout_width="wrap_content" > diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml index 93ec481258f5..089a54db5e86 100644 --- a/packages/SystemUI/res/values/donottranslate.xml +++ b/packages/SystemUI/res/values/donottranslate.xml @@ -18,8 +18,9 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- For formatting day of week and date in DateView. %1$s is DOW, %2$s is date. - In Roman locales we now show only the date, but DOW is available for other locales if - necessary. --> - <string name="status_bar_date_formatter">%2$s</string> + We show both (DOW on one line, then the date) but this can be overridden for locales as + necessary. + --> + <string name="status_bar_date_formatter">%1$s\n%2$s</string> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 1a6cae2ec2f7..a0d7b13a012e 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -256,7 +256,12 @@ <!-- Content description of the WIFI signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_wifi_three_bars">Wi-Fi three bars.</string> <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_wifi_signal_full">Wi-Fi signal full.</string> + <string name="accessibility_wifi_signal_full">WiFi signal full.</string> + <string name="accessibility_no_wimax">No WiMAX.</string> + <string name="accessibility_wimax_one_bar">WiMAX one bar.</string> + <string name="accessibility_wimax_two_bars">WiMAX two bars.</string> + <string name="accessibility_wimax_three_bars">WiMAX three bars.</string> + <string name="accessibility_wimax_signal_full">WiMAX signal full.</string> <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_data_connection_gprs">GPRS</string> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index c6a59d33eb0e..b0e6968c46fd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -350,7 +350,11 @@ public class PhoneStatusBar extends StatusBar { (SignalClusterView)sb.findViewById(R.id.signal_cluster); mNetworkController.addSignalCluster(signalCluster); signalCluster.setNetworkController(mNetworkController); - + final ImageView wimaxRSSI = + (ImageView)sb.findViewById(R.id.wimax_signal); + if (wimaxRSSI != null) { + mNetworkController.addWimaxIconView(wimaxRSSI); + } // Recents Panel mRecentTasksLoader = new RecentTasksLoader(context); updateRecentsPanel(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java index 13fb03e6c677..f45426bb260c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java @@ -34,4 +34,11 @@ public class AccessibilityContentDescriptions { R.string.accessibility_wifi_three_bars, R.string.accessibility_wifi_signal_full }; + static final int[] WIMAX_CONNECTION_STRENGTH = { + R.string.accessibility_no_wimax, + R.string.accessibility_wimax_one_bar, + R.string.accessibility_wimax_two_bars, + R.string.accessibility_wimax_three_bars, + R.string.accessibility_wimax_signal_full + }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index a3058166903f..f77e93f1ba84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -31,6 +31,7 @@ import android.net.NetworkInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wimax.WimaxManagerConstants; import android.os.Binder; import android.os.Handler; import android.os.Message; @@ -90,6 +91,7 @@ public class NetworkController extends BroadcastReceiver { String mContentDescriptionPhoneSignal; String mContentDescriptionWifi; + String mContentDescriptionWimax; String mContentDescriptionCombinedSignal; String mContentDescriptionDataType; @@ -108,6 +110,14 @@ public class NetworkController extends BroadcastReceiver { private int mBluetoothTetherIconId = com.android.internal.R.drawable.stat_sys_tether_bluetooth; + //wimax + private boolean mIsWimaxEnabled = false; + private boolean mWimaxConnected = false; + private boolean mWimaxIdle = false; + private int mWimaxIconId = 0; + private int mWimaxSignal = 0; + private int mWimaxState = 0; + private int mWimaxExtraState = 0; // data connectivity (regardless of state, can we access the internet?) // state of inet connection - 0 not connected, 100 connected private int mInetCondition = 0; @@ -121,6 +131,7 @@ public class NetworkController extends BroadcastReceiver { ArrayList<ImageView> mDataDirectionIconViews = new ArrayList<ImageView>(); ArrayList<ImageView> mDataDirectionOverlayIconViews = new ArrayList<ImageView>(); ArrayList<ImageView> mWifiIconViews = new ArrayList<ImageView>(); + ArrayList<ImageView> mWimaxIconViews = new ArrayList<ImageView>(); ArrayList<ImageView> mCombinedSignalIconViews = new ArrayList<ImageView>(); ArrayList<ImageView> mDataTypeIconViews = new ArrayList<ImageView>(); ArrayList<TextView> mLabelViews = new ArrayList<TextView>(); @@ -129,6 +140,7 @@ public class NetworkController extends BroadcastReceiver { int mLastDataDirectionIconId = -1; int mLastDataDirectionOverlayIconId = -1; int mLastWifiIconId = -1; + int mLastWimaxIconId = -1; int mLastCombinedSignalIconId = -1; int mLastDataTypeIconId = -1; String mLastLabel = ""; @@ -164,6 +176,7 @@ public class NetworkController extends BroadcastReceiver { // set up the default wifi icon, used when no radios have ever appeared updateWifiIcons(); + updateWimaxIcons(); // telephony mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); @@ -200,6 +213,13 @@ public class NetworkController extends BroadcastReceiver { filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); + boolean isWimaxConfigEnabled = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_wimaxEnabled); + if(isWimaxConfigEnabled) { + filter.addAction(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION); + filter.addAction(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION); + filter.addAction(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION); + } context.registerReceiver(this, filter); // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it @@ -224,6 +244,9 @@ public class NetworkController extends BroadcastReceiver { public void addWifiIconView(ImageView v) { mWifiIconViews.add(v); } + public void addWimaxIconView(ImageView v) { + mWimaxIconViews.add(v); + } public void addCombinedSignalIconView(ImageView v) { mCombinedSignalIconViews.add(v); @@ -285,6 +308,11 @@ public class NetworkController extends BroadcastReceiver { } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { updateAirplaneMode(); refreshViews(); + } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) || + action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) || + action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) { + updateWimaxState(intent); + refreshViews(); } } @@ -735,6 +763,51 @@ public class NetworkController extends BroadcastReceiver { } + // ===== Wimax =================================================================== + + private final void updateWimaxState(Intent intent) { + final String action = intent.getAction(); + boolean wasConnected = mWimaxConnected; + if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) { + int wimaxStatus = intent.getIntExtra(WimaxManagerConstants.EXTRA_4G_STATE, + WimaxManagerConstants.NET_4G_STATE_UNKNOWN); + mIsWimaxEnabled = (wimaxStatus == + WimaxManagerConstants.NET_4G_STATE_ENABLED)? true : false; + } else if (action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION)) { + mWimaxSignal = intent.getIntExtra(WimaxManagerConstants.EXTRA_NEW_SIGNAL_LEVEL, 0); + } else if (action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) { + mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE, + WimaxManagerConstants.NET_4G_STATE_UNKNOWN); + mWimaxExtraState = intent.getIntExtra( + WimaxManagerConstants.EXTRA_WIMAX_STATE_DETAIL, + WimaxManagerConstants.NET_4G_STATE_UNKNOWN); + mWimaxConnected = (mWimaxState == + WimaxManagerConstants.WIMAX_STATE_CONNECTED) ? true : false; + mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE)? true : false; + } + updateWimaxIcons(); + } + private void updateWimaxIcons() { + Slog.d(TAG, "in .... updateWimaxIcons function : "+mIsWimaxEnabled); + if (mIsWimaxEnabled) { + if (mWimaxConnected) { + Slog.d(TAG, "in .... updateWimaxIcons function WiMAX COnnected"); + if (mWimaxIdle) + mWimaxIconId = WimaxIcons.WIMAX_IDLE; + else + mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[mInetCondition][mWimaxSignal]; + mContentDescriptionWimax = mContext.getString( + AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]); + } else { + Slog.d(TAG, "in .... updateWimaxIcons function WiMAX Disconnected"); + mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED; + mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax); + } + } else { + Slog.d(TAG, "in .... updateWimaxIcons function wimax icon id 0"); + mWimaxIconId = 0; + } + } // ===== Full or limited Internet connectivity ================================== private void updateConnectivity(Intent intent) { @@ -761,6 +834,7 @@ public class NetworkController extends BroadcastReceiver { // We want to update all the icons, all at once, for any condition change updateDataNetType(); + updateWimaxIcons(); updateDataIcon(); updateTelephonySignalStrength(); updateWifiIcons(); @@ -945,6 +1019,21 @@ public class NetworkController extends BroadcastReceiver { } } + // the wimax icon on phones + if (mLastWimaxIconId != mWimaxIconId) { + mLastWimaxIconId = mWimaxIconId; + N = mWimaxIconViews.size(); + for (int i=0; i<N; i++) { + final ImageView v = mWimaxIconViews.get(i); + if (mWimaxIconId == 0) { + v.setVisibility(View.INVISIBLE); + } else { + v.setVisibility(View.VISIBLE); + v.setImageResource(mWimaxIconId); + v.setContentDescription(mContentDescriptionWimax); + } + } + } // the combined data signal icon if (mLastCombinedSignalIconId != combinedSignalIconId) { mLastCombinedSignalIconId = combinedSignalIconId; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java new file mode 100644 index 000000000000..86054895e8af --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java @@ -0,0 +1,37 @@ +/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import com.android.systemui.R;
+
+class WimaxIcons {
+ static final int[][] WIMAX_SIGNAL_STRENGTH = {
+ { R.drawable.stat_sys_data_wimax_signal_0,
+ R.drawable.stat_sys_data_wimax_signal_1,
+ R.drawable.stat_sys_data_wimax_signal_2,
+ R.drawable.stat_sys_data_wimax_signal_3 },
+ { R.drawable.stat_sys_data_wimax_signal_0_fully,
+ R.drawable.stat_sys_data_wimax_signal_1_fully,
+ R.drawable.stat_sys_data_wimax_signal_2_fully,
+ R.drawable.stat_sys_data_wimax_signal_3_fully }
+ };
+
+ static final int WIMAX_DISCONNECTED =
+ R.drawable.stat_sys_data_wimax_signal_disconnected;
+ static final int WIMAX_IDLE = R.drawable.stat_sys_data_wimax_signal_idle;
+ static final int WIFI_LEVEL_COUNT = WIMAX_SIGNAL_STRENGTH[0].length;
+}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 81e1901f398a..0f21bdb475a4 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -360,8 +360,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mHasOverlay = true; // Continue showing FaceLock area until dialer comes up or call is resumed - if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled() && mFaceLockServiceRunning) { + if (usingFaceLock() && mFaceLockServiceRunning) { showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT); } @@ -582,8 +581,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler bindToFaceLock(); // Show FaceLock area, but only for a little bit so lockpattern will become visible if // FaceLock fails to start or crashes - if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled()) { + if (usingFaceLock()) { showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT); } } else { @@ -653,11 +651,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler ((KeyguardScreen) mUnlockScreen).onResume(); } - if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled() && !mHasOverlay) { + if (usingFaceLock() && !mHasOverlay) { // Note that show() gets called before the screen turns off to set it up for next time // it is turned on. We don't want to set a timeout on the FaceLock area here because it - // may be gone by the time the screen is turned on again. We set the timout when the + // may be gone by the time the screen is turned on again. We set the timeout when the // screen turns on instead. showFaceLockArea(); } else { @@ -854,7 +851,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler if (mode == Mode.UnlockScreen) { final UnlockMode unlockMode = getUnlockMode(); if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) { + boolean restartFaceLock = stopFaceLockIfRunning(); recreateUnlockScreen(unlockMode); + if (restartFaceLock) activateFaceLockIfAble(); } } @@ -1147,28 +1146,33 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // Everything below pertains to FaceLock - might want to separate this out - // Take care of FaceLock area when layout is created + // Indicates whether FaceLock is in use + private boolean usingFaceLock() { + return (mLockPatternUtils.usingBiometricWeak() && + mLockPatternUtils.isBiometricWeakInstalled()); + } + + // Takes care of FaceLock area when layout is created private void initializeFaceLockAreaView(View view) { - if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled()) { + if (usingFaceLock()) { mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView); if (mFaceLockAreaView == null) { Log.e(TAG, "Layout does not have faceLockAreaView and FaceLock is enabled"); - } else { - if (mBoundToFaceLockService) { - // If we are creating a layout when we are already bound to FaceLock, then we - // are undergoing an orientation change. Stop FaceLock and restart it in the - // new location. - if (DEBUG) Log.d(TAG, "Restarting FL - creating view while already bound"); - stopAndUnbindFromFaceLock(); - activateFaceLockIfAble(); - } } } else { mFaceLockAreaView = null; // Set to null if not using FaceLock } } + // Stops FaceLock if it is running and reports back whether it was running or not + private boolean stopFaceLockIfRunning() { + if (usingFaceLock() && mBoundToFaceLockService) { + stopAndUnbindFromFaceLock(); + return true; + } + return false; + } + // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops // This needs to be done in a handler because the call could be coming from a callback from the // FaceLock service that is in a thread that can't modify the UI @@ -1221,8 +1225,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // Binds to FaceLock service. This call does not tell it to start, but it causes the service // to call the onServiceConnected callback, which then starts FaceLock. public void bindToFaceLock() { - if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled()) { + if (usingFaceLock()) { if (!mBoundToFaceLockService) { if (DEBUG) Log.d(TAG, "before bind to FaceLock service"); mContext.bindService(new Intent(IFaceLockInterface.class.getName()), @@ -1238,8 +1241,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // Tells FaceLock to stop and then unbinds from the FaceLock service public void stopAndUnbindFromFaceLock() { - if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled()) { + if (usingFaceLock()) { stopFaceLock(); if (mBoundToFaceLockService) { @@ -1300,8 +1302,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // Tells the FaceLock service to start displaying its UI and perform recognition public void startFaceLock(IBinder windowToken, int x, int y, int h, int w) { - if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled()) { + if (usingFaceLock()) { synchronized (mFaceLockServiceRunningLock) { if (!mFaceLockServiceRunning) { if (DEBUG) Log.d(TAG, "Starting FaceLock"); @@ -1322,8 +1323,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // Tells the FaceLock service to stop displaying its UI and stop recognition public void stopFaceLock() { - if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled()) { + if (usingFaceLock()) { // Note that attempting to stop FaceLock when it's not running is not an issue. // FaceLock can return, which stops it and then we try to stop it when the // screen is turned off. That's why we check. diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 3469483330d6..24a2420428d3 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -34,6 +34,7 @@ import android.view.ViewGroup; import android.widget.*; import android.util.Log; import android.media.AudioManager; +import android.provider.MediaStore; import android.provider.Settings; import java.io.File; @@ -225,9 +226,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen { mCallback.goToUnlockScreen(); } else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscape if (!mCameraDisabled) { - // Broadcast an intent to start the Camera - Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); - mContext.sendOrderedBroadcast(intent, null); + // Start the Camera + Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); mCallback.goToUnlockScreen(); } else { toggleRingMode(); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 7d97246c1fa6..aa1c81c07b9e 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -493,7 +493,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { return true; } if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) || - (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) { + (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK + || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK + || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) { // enable accelerometer if we are docked in a dock that enables accelerometer // orientation management, return true; @@ -3137,7 +3139,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { // enable 180 degree rotation while docked. preferredRotation = mCarDockEnablesAccelerometer ? sensorRotation : mCarDockRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK + } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK + || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK + || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { // Ignore sensor when in desk dock unless explicitly enabled. // This case can override the behavior of NOSENSOR, and can also diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 96e8eb980fd6..ff262f12ab61 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -2066,9 +2066,14 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track // The first time a track is added we wait // for all its buffers to be filled before processing it mAudioMixer->setActiveTrack(track->name()); - // make sure that we have enough frames to mix one full buffer + // make sure that we have enough frames to mix one full buffer. + // enforce this condition only once to enable draining the buffer in case the client + // app does not call stop() and relies on underrun to stop: + // hence the test on (track->mRetryCount >= kMaxTrackRetries) meaning the track was mixed + // during last round uint32_t minFrames = 1; - if (!track->isStopped() && !track->isPausing()) { + if (!track->isStopped() && !track->isPausing() && + (track->mRetryCount >= kMaxTrackRetries)) { if (t->sampleRate() == (int)mSampleRate) { minFrames = mFrameCount; } else { diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 8c42f3133a0c..4af61129e211 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -26,8 +26,10 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import android.bluetooth.BluetoothTetheringDataTracker; import android.content.ContentResolver; import android.content.Context; +import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.DummyDataStateTracker; @@ -51,6 +53,7 @@ import android.net.Proxy; import android.net.ProxyProperties; import android.net.RouteInfo; import android.net.wifi.WifiStateTracker; +import android.net.wimax.WimaxManagerConstants; import android.os.Binder; import android.os.FileUtils; import android.os.Handler; @@ -78,10 +81,14 @@ import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; import com.google.android.collect.Lists; import com.google.android.collect.Sets; - +import dalvik.system.DexClassLoader; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.InvocationTargetException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -491,6 +498,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance(); mNetTrackers[netType].startMonitoring(context, mHandler); break; + case ConnectivityManager.TYPE_WIMAX: + mNetTrackers[netType] = makeWimaxStateTracker(); + if (mNetTrackers[netType]!= null) { + mNetTrackers[netType].startMonitoring(context, mHandler); + } + break; case ConnectivityManager.TYPE_ETHERNET: mNetTrackers[netType] = EthernetDataTracker.getInstance(); mNetTrackers[netType].startMonitoring(context, mHandler); @@ -531,7 +544,81 @@ public class ConnectivityService extends IConnectivityManager.Stub { loadGlobalProxy(); } +private NetworkStateTracker makeWimaxStateTracker() { + //Initialize Wimax + DexClassLoader wimaxClassLoader; + Class wimaxStateTrackerClass = null; + Class wimaxServiceClass = null; + Class wimaxManagerClass; + String wimaxJarLocation; + String wimaxLibLocation; + String wimaxManagerClassName; + String wimaxServiceClassName; + String wimaxStateTrackerClassName; + + NetworkStateTracker wimaxStateTracker = null; + + boolean isWimaxEnabled = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_wimaxEnabled); + + if (isWimaxEnabled) { + try { + wimaxJarLocation = mContext.getResources().getString( + com.android.internal.R.string.config_wimaxServiceJarLocation); + wimaxLibLocation = mContext.getResources().getString( + com.android.internal.R.string.config_wimaxNativeLibLocation); + wimaxManagerClassName = mContext.getResources().getString( + com.android.internal.R.string.config_wimaxManagerClassname); + wimaxServiceClassName = mContext.getResources().getString( + com.android.internal.R.string.config_wimaxServiceClassname); + wimaxStateTrackerClassName = mContext.getResources().getString( + com.android.internal.R.string.config_wimaxStateTrackerClassname); + + log("wimaxJarLocation: " + wimaxJarLocation); + wimaxClassLoader = new DexClassLoader(wimaxJarLocation, + new ContextWrapper(mContext).getCacheDir().getAbsolutePath(), + wimaxLibLocation, ClassLoader.getSystemClassLoader()); + + try { + wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName); + wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName); + wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName); + } catch (ClassNotFoundException ex) { + loge("Exception finding Wimax classes: " + ex.toString()); + return null; + } + } catch(Resources.NotFoundException ex) { + loge("Wimax Resources does not exist!!! "); + return null; + } + try { + log("Starting Wimax Service... "); + + Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor + (new Class[] {Context.class, Handler.class}); + wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext, + mHandler); + + Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor + (new Class[] {Context.class, wimaxStateTrackerClass}); + wmxSrvConst.setAccessible(true); + IBinder svcInvoker = (IBinder)wmxSrvConst.newInstance(mContext, wimaxStateTracker); + wmxSrvConst.setAccessible(false); + + ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker); + + } catch(Exception ex) { + loge("Exception creating Wimax classes: " + ex.toString()); + return null; + } + } else { + loge("Wimax is not enabled or not added to the network attributes!!! "); + return null; + } + + return wimaxStateTracker; + } /** * Sets the preferred network. * @param preference the new preference diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java index dea900786874..64789d33692d 100644 --- a/services/java/com/android/server/DockObserver.java +++ b/services/java/com/android/server/DockObserver.java @@ -82,7 +82,9 @@ class DockObserver extends UEventObserver { // Don't force screen on when undocking from the desk dock. // The change in power state will do this anyway. // FIXME - we should be configurable. - if (mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK || + if ((mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK + && mPreviousDockState != Intent.EXTRA_DOCK_STATE_LE_DESK + && mPreviousDockState != Intent.EXTRA_DOCK_STATE_HE_DESK) || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) { mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(), false, true); diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 6887de32e112..da960aeae5e3 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -1136,12 +1136,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub final StringBuilder command = new StringBuilder(); command.append("bandwidth removeiquota ").append(iface); + mActiveQuotaIfaces.remove(iface); + mActiveAlertIfaces.remove(iface); + try { // TODO: support quota shared across interfaces mConnector.doCommand(command.toString()); - mActiveQuotaIfaces.remove(iface); - mActiveAlertIfaces.remove(iface); } catch (NativeDaemonConnectorException e) { + // TODO: include current iptables state throw new IllegalStateException("Error communicating to native daemon", e); } } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 1b0addfdae4e..6b23b33ae7bb 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -100,10 +100,13 @@ public class PowerManagerService extends IPowerManager.Stub private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec private static final int LONG_DIM_TIME = 7000; // t+N-5 sec - // How long to wait to debounce light sensor changes. + // How long to wait to debounce light sensor changes in milliseconds private static final int LIGHT_SENSOR_DELAY = 2000; - // For debouncing the proximity sensor. + // light sensor events rate in microseconds + private static final int LIGHT_SENSOR_RATE = 1000000; + + // For debouncing the proximity sensor in milliseconds private static final int PROXIMITY_SENSOR_DELAY = 1000; // trigger proximity if distance is less than 5 cm @@ -3049,7 +3052,7 @@ public class PowerManagerService extends IPowerManager.Stub try { if (enable) { mSensorManager.registerListener(mLightListener, mLightSensor, - SensorManager.SENSOR_DELAY_NORMAL); + LIGHT_SENSOR_RATE); } else { mSensorManager.unregisterListener(mLightListener); mHandler.removeCallbacks(mAutoBrightnessTask); diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 01eade136f19..3c65255ca5bf 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -619,12 +619,7 @@ public class WifiService extends IWifiManager.Stub { */ public WifiConfiguration getWifiApConfiguration() { enforceAccessPermission(); - if (mWifiStateMachineChannel != null) { - return mWifiStateMachine.syncGetWifiApConfiguration(mWifiStateMachineChannel); - } else { - Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); - return null; - } + return mWifiStateMachine.syncGetWifiApConfiguration(); } /** diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 4fe8119ba19b..05d42ada146c 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1220,6 +1220,8 @@ public final class ActivityManagerService extends ActivityManagerNative } Thread thread = new Thread() { @Override public void run() { + StringBuilder dropBuilder = new StringBuilder(1024); + StringBuilder logBuilder = new StringBuilder(1024); try { java.lang.Process proc = Runtime.getRuntime().exec(new String[] { "procrank", }); @@ -1233,16 +1235,29 @@ public final class ActivityManagerService extends ActivityManagerNative break; } if (line.length() > 0) { - Slog.i(TAG, line); + logBuilder.append(line); + logBuilder.append('\n'); } + dropBuilder.append(line); + dropBuilder.append('\n'); } converter.close(); } catch (IOException e) { } StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true); - Slog.i(TAG, sw.toString()); + StringWriter catSw = new StringWriter(); + PrintWriter catPw = new PrintWriter(catSw); + dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true, catPw); + String memUsage = sw.toString(); + dropBuilder.append('\n'); + dropBuilder.append(memUsage); + dropBuilder.append(catSw.toString()); + logBuilder.append(memUsage); + addErrorToDropBox("watchdog", null, "system_server", null, + null, "Low on memory -- no more background processes", + dropBuilder.toString(), null, null); + Slog.i(TAG, logBuilder.toString()); synchronized (ActivityManagerService.this) { long now = SystemClock.uptimeMillis(); if (mLastMemUsageReportTime < now) { @@ -1394,7 +1409,7 @@ public final class ActivityManagerService extends ActivityManagerNative return; } - mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false); + mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null); } } @@ -3192,7 +3207,49 @@ public final class ActivityManagerService extends ActivityManagerNative return; } killPackageProcessesLocked(packageName, pkgUid, - ProcessList.SERVICE_ADJ, false, true, true, false); + ProcessList.SERVICE_ADJ, false, true, true, false, "kill background"); + } + } finally { + Binder.restoreCallingIdentity(callingId); + } + } + + public void killAllBackgroundProcesses() { + if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) + != PackageManager.PERMISSION_GRANTED) { + String msg = "Permission Denial: killAllBackgroundProcesses() from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + + long callingId = Binder.clearCallingIdentity(); + try { + synchronized(this) { + ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(); + for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) { + final int NA = apps.size(); + for (int ia=0; ia<NA; ia++) { + ProcessRecord app = apps.valueAt(ia); + if (app.persistent) { + // we don't kill persistent processes + continue; + } + if (app.removed) { + procs.add(app); + } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) { + app.removed = true; + procs.add(app); + } + } + } + + int N = procs.size(); + for (int i=0; i<N; i++) { + removeProcessLocked(procs.get(i), false, true, "kill all background"); + } } } finally { Binder.restoreCallingIdentity(callingId); @@ -3364,7 +3421,7 @@ public final class ActivityManagerService extends ActivityManagerNative private final boolean killPackageProcessesLocked(String packageName, int uid, int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit, - boolean evenPersistent) { + boolean evenPersistent, String reason) { ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(); // Remove all processes this package may have touched: all with the @@ -3399,7 +3456,7 @@ public final class ActivityManagerService extends ActivityManagerNative int N = procs.size(); for (int i=0; i<N; i++) { - removeProcessLocked(procs.get(i), callerWillRestart, allowRestart); + removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason); } return N > 0; } @@ -3430,7 +3487,7 @@ public final class ActivityManagerService extends ActivityManagerNative } boolean didSomething = killPackageProcessesLocked(name, uid, -100, - callerWillRestart, false, doit, evenPersistent); + callerWillRestart, false, doit, evenPersistent, "force stop"); TaskRecord lastTask = null; for (i=0; i<mMainStack.mHistory.size(); i++) { @@ -3518,11 +3575,11 @@ public final class ActivityManagerService extends ActivityManagerNative } private final boolean removeProcessLocked(ProcessRecord app, - boolean callerWillRestart, boolean allowRestart) { + boolean callerWillRestart, boolean allowRestart, String reason) { final String name = app.processName; final int uid = app.info.uid; if (DEBUG_PROCESSES) Slog.d( - TAG, "Force removing process " + app + " (" + name + TAG, "Force removing proc " + app.toShortString() + " (" + name + "/" + uid + ")"); mProcessNames.remove(name, uid); @@ -3537,9 +3594,10 @@ public final class ActivityManagerService extends ActivityManagerNative mPidsSelfLocked.remove(pid); mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } + Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason); handleAppDiedLocked(app, true, allowRestart); mLruProcesses.remove(app); - Process.killProcess(pid); + Process.killProcessQuiet(pid); if (app.persistent) { if (!callerWillRestart) { @@ -6846,7 +6904,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=procsToKill.size()-1; i>=0; i--) { ProcessRecord proc = procsToKill.get(i); Slog.i(TAG, "Removing system update proc: " + proc); - removeProcessLocked(proc, true, false); + removeProcessLocked(proc, true, false, "system update done"); } } @@ -7042,7 +7100,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Don't let services in this process be restarted and potentially // annoy the user repeatedly. Unless it is persistent, since those // processes run critical code. - removeProcessLocked(app, false, false); + removeProcessLocked(app, false, false, "crash"); mMainStack.resumeTopActivityLocked(null); return false; } @@ -9298,8 +9356,10 @@ public final class ActivityManagerService extends ActivityManagerNative } final void dumpApplicationMemoryUsage(FileDescriptor fd, - PrintWriter pw, String prefix, String[] args, boolean brief) { + PrintWriter pw, String prefix, String[] args, boolean brief, + PrintWriter categoryPw) { boolean dumpAll = false; + boolean oomOnly = false; int opti = 0; while (opti < args.length) { @@ -9310,9 +9370,12 @@ public final class ActivityManagerService extends ActivityManagerNative opti++; if ("-a".equals(opt)) { dumpAll = true; + } else if ("--oom".equals(opt)) { + oomOnly = true; } else if ("-h".equals(opt)) { - pw.println("meminfo dump options: [-a] [process]"); + pw.println("meminfo dump options: [-a] [--oom] [process]"); pw.println(" -a: include all available information for each process."); + pw.println(" --oom: only show processes organized by oom adj."); pw.println("If [process] is specified it can be the name or "); pw.println("pid of a specific process to dump."); return; @@ -9438,7 +9501,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - if (!brief) { + if (!brief && !oomOnly) { pw.println(); pw.println("Total PSS by process:"); dumpMemItems(pw, " ", procMems, true); @@ -9446,10 +9509,11 @@ public final class ActivityManagerService extends ActivityManagerNative } pw.println("Total PSS by OOM adjustment:"); dumpMemItems(pw, " ", oomMems, false); - if (!brief) { - pw.println(); - pw.println("Total PSS by category:"); - dumpMemItems(pw, " ", catMems, true); + if (!oomOnly) { + PrintWriter out = categoryPw != null ? categoryPw : pw; + out.println(); + out.println("Total PSS by category:"); + dumpMemItems(out, " ", catMems, true); } pw.println(); pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb"); diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 289ea1fe1019..2a1b1db0bf77 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -190,6 +190,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int MSG_METERED_IFACES_CHANGED = 2; private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3; private static final int MSG_PROCESS_DIED = 4; + private static final int MSG_LIMIT_REACHED = 5; private final Context mContext; private final IActivityManager mActivityManager; @@ -225,8 +226,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** Set of currently active {@link Notification} tags. */ private HashSet<String> mActiveNotifs = Sets.newHashSet(); - /** Current values from {@link #setPolicyDataEnable(int, boolean)}. */ - private SparseBooleanArray mActiveNetworkEnabled = new SparseBooleanArray(); /** Foreground at both UID and PID granularity. */ private SparseBooleanArray mUidForeground = new SparseBooleanArray(); @@ -424,19 +423,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // only someone like NMS should be calling us mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - synchronized (mRulesLock) { - if (mMeteredIfaces.contains(iface) && !LIMIT_GLOBAL_ALERT.equals(limitName)) { - try { - // force stats update to make sure we have numbers that - // caused alert to trigger. - mNetworkStats.forceUpdate(); - } catch (RemoteException e) { - // ignored; service lives in system_server - } - - updateNetworkEnabledLocked(); - updateNotificationsLocked(); - } + if (!LIMIT_GLOBAL_ALERT.equals(limitName)) { + mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget(); } } }; @@ -1481,6 +1469,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } return true; } + case MSG_LIMIT_REACHED: { + final String iface = (String) msg.obj; + + synchronized (mRulesLock) { + if (mMeteredIfaces.contains(iface)) { + try { + // force stats update to make sure we have + // numbers that caused alert to trigger. + mNetworkStats.forceUpdate(); + } catch (RemoteException e) { + // ignored; service lives in system_server + } + + updateNetworkEnabledLocked(); + updateNotificationsLocked(); + } + } + return true; + } default: { return false; } @@ -1519,21 +1526,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } /** - * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}, - * dispatching only when actually changed. + * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}. */ private void setPolicyDataEnable(int networkType, boolean enabled) { - synchronized (mActiveNetworkEnabled) { - final boolean prevEnabled = mActiveNetworkEnabled.get(networkType, true); - if (prevEnabled == enabled) return; - - try { - mConnManager.setPolicyDataEnable(networkType, enabled); - } catch (RemoteException e) { - // ignored; service lives in system_server - } - - mActiveNetworkEnabled.put(networkType, enabled); + try { + mConnManager.setPolicyDataEnable(networkType, enabled); + } catch (RemoteException e) { + // ignored; service lives in system_server } } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 494c655ba048..77b0d96f4242 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -152,10 +152,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String TAG_NETSTATS_ERROR = "netstats_error"; - private static final String DEV = "dev"; - private static final String XT = "xt"; - private static final String UID = "uid"; - private final Context mContext; private final INetworkManagementService mNetworkManager; private final IAlarmManager mAlarmManager; @@ -278,6 +274,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { readNetworkXtStatsLocked(); } + // bootstrap initial stats to prevent double-counting later + bootstrapStats(); + // watch for network interfaces to be claimed final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); @@ -311,9 +310,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { registerPollAlarmLocked(); registerGlobalAlert(); - // bootstrap initial stats to prevent double-counting later - bootstrapStats(); - mDropBox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE); } @@ -837,9 +833,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // persist when enough network data has occurred final long persistNetworkDevDelta = computeStatsDelta( - mLastPersistNetworkDevSnapshot, networkDevSnapshot, true, DEV).getTotalBytes(); + mLastPersistNetworkDevSnapshot, networkDevSnapshot, true, "devp").getTotalBytes(); final long persistNetworkXtDelta = computeStatsDelta( - mLastPersistNetworkXtSnapshot, networkXtSnapshot, true, XT).getTotalBytes(); + mLastPersistNetworkXtSnapshot, networkXtSnapshot, true, "xtp").getTotalBytes(); final boolean networkOverThreshold = persistNetworkDevDelta > threshold || persistNetworkXtDelta > threshold; if (persistForce || (persistNetwork && networkOverThreshold)) { @@ -851,7 +847,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // persist when enough uid data has occurred final long persistUidDelta = computeStatsDelta( - mLastPersistUidSnapshot, uidSnapshot, true, UID).getTotalBytes(); + mLastPersistUidSnapshot, uidSnapshot, true, "uidp").getTotalBytes(); if (persistForce || (persistUid && persistUidDelta > threshold)) { writeUidStatsLocked(); mLastPersistUidSnapshot = uidSnapshot; @@ -880,7 +876,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HashSet<String> unknownIface = Sets.newHashSet(); final NetworkStats delta = computeStatsDelta( - mLastPollNetworkDevSnapshot, networkDevSnapshot, false, DEV); + mLastPollNetworkDevSnapshot, networkDevSnapshot, false, "dev"); final long timeStart = currentTime - delta.getElapsedRealtime(); NetworkStats.Entry entry = null; @@ -910,7 +906,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HashSet<String> unknownIface = Sets.newHashSet(); final NetworkStats delta = computeStatsDelta( - mLastPollNetworkXtSnapshot, networkXtSnapshot, false, XT); + mLastPollNetworkXtSnapshot, networkXtSnapshot, false, "xt"); final long timeStart = currentTime - delta.getElapsedRealtime(); NetworkStats.Entry entry = null; @@ -940,9 +936,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { ensureUidStatsLoadedLocked(); final NetworkStats delta = computeStatsDelta( - mLastPollUidSnapshot, uidSnapshot, false, UID); + mLastPollUidSnapshot, uidSnapshot, false, "uid"); final NetworkStats operationsDelta = computeStatsDelta( - mLastPollOperationsSnapshot, mOperations, false, UID); + mLastPollOperationsSnapshot, mOperations, false, "uidop"); final long timeStart = currentTime - delta.getElapsedRealtime(); NetworkStats.Entry entry = null; @@ -971,8 +967,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } mLastPollUidSnapshot = uidSnapshot; - mLastPollOperationsSnapshot = mOperations; - mOperations = new NetworkStats(0L, 10); + mLastPollOperationsSnapshot = mOperations.clone(); } /** @@ -1516,7 +1511,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // record error for debugging final StringBuilder builder = new StringBuilder(); - builder.append("found non-monotonic " + type + "values at left[" + e.leftIndex + builder.append("found non-monotonic " + type + " values at left[" + e.leftIndex + "] - right[" + e.rightIndex + "]\n"); builder.append("left=").append(e.left).append('\n'); builder.append("right=").append(e.right).append('\n'); diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index d2d2d8baa066..c2c6b4d469be 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -478,8 +478,9 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection if (ns < 0) return BAD_VALUE; - if (ns == 0) { - ns = sensor->getSensor().getMinDelayNs(); + nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs(); + if (ns < minDelayNs) { + ns = minDelayNs; } if (ns < MINIMUM_EVENTS_PERIOD) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8f4fdb8fed5c..1b00e9380a62 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1217,23 +1217,25 @@ void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state, sp<Client> client( static_cast<Client *>(s.client.get()) ); transactionFlags |= setClientStateLocked(client, s.state); } + if (transactionFlags) { + // this triggers the transaction setTransactionFlags(transactionFlags); - } - // if this is a synchronous transaction, wait for it to take effect before - // returning. - if (flags & eSynchronous) { - mTransationPending = true; - } - while (mTransationPending) { - status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); - if (CC_UNLIKELY(err != NO_ERROR)) { - // just in case something goes wrong in SF, return to the - // called after a few seconds. - LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!"); - mTransationPending = false; - break; + // if this is a synchronous transaction, wait for it to take effect + // before returning. + if (flags & eSynchronous) { + mTransationPending = true; + } + while (mTransationPending) { + status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); + if (CC_UNLIKELY(err != NO_ERROR)) { + // just in case something goes wrong in SF, return to the + // called after a few seconds. + LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!"); + mTransationPending = false; + break; + } } } } diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 34f88489ed6a..f2ccb5bf016e 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1513,14 +1513,65 @@ public class PhoneNumberUtils static final int MIN_MATCH = 7; /** - * isEmergencyNumber: checks a given number against the list of - * emergency numbers provided by the RIL and SIM card. + * Checks a given number against the list of + * emergency numbers provided by the RIL and SIM card. * * @param number the number to look up. - * @return if the number is in the list of emergency numbers - * listed in the ril / sim, then return true, otherwise false. + * @return true if the number is in the list of emergency numbers + * listed in the RIL / SIM, otherwise return false. */ public static boolean isEmergencyNumber(String number) { + // Return true only if the specified number *exactly* matches + // one of the emergency numbers listed by the RIL / SIM. + return isEmergencyNumberInternal(number, true /* useExactMatch */); + } + + /** + * Checks if given number might *potentially* result in + * a call to an emergency service on the current network. + * + * Specifically, this method will return true if the specified number + * is an emergency number according to the list managed by the RIL or + * SIM, *or* if the specified number simply starts with the same + * digits as any of the emergency numbers listed in the RIL / SIM. + * + * This method is intended for internal use by the phone app when + * deciding whether to allow ACTION_CALL intents from 3rd party apps + * (where we're required to *not* allow emergency calls to be placed.) + * + * @param number the number to look up. + * @return true if the number is in the list of emergency numbers + * listed in the RIL / SIM, *or* if the number starts with the + * same digits as any of those emergency numbers. + * + * @hide + */ + public static boolean isPotentialEmergencyNumber(String number) { + // Check against the emergency numbers listed by the RIL / SIM, + // and *don't* require an exact match. + return isEmergencyNumberInternal(number, false /* useExactMatch */); + } + + /** + * Helper function for isEmergencyNumber(String) and + * isPotentialEmergencyNumber(String). + * + * @param number the number to look up. + * + * @param useExactMatch if true, consider a number to be an emergency + * number only if it *exactly* matches a number listed in + * the RIL / SIM. If false, a number is considered to be an + * emergency number if it simply starts with the same digits + * as any of the emergency numbers listed in the RIL / SIM. + * (Setting useExactMatch to false allows you to identify + * number that could *potentially* result in emergency calls + * since many networks will actually ignore trailing digits + * after a valid emergency number.) + * + * @return true if the number is in the list of emergency numbers + * listed in the RIL / sim, otherwise return false. + */ + private static boolean isEmergencyNumberInternal(String number, boolean useExactMatch) { // If the number passed in is null, just return false: if (number == null) return false; @@ -1540,16 +1591,26 @@ public class PhoneNumberUtils // searches through the comma-separated list for a match, // return true if one is found. for (String emergencyNum : numbers.split(",")) { - if (number.startsWith(emergencyNum)) { - return true; + if (useExactMatch) { + if (number.equals(emergencyNum)) { + return true; + } + } else { + if (number.startsWith(emergencyNum)) { + return true; + } } } // no matches found against the list! return false; } - //no ecclist system property, so use our own list. - return (number.startsWith("112") || number.startsWith("911")); + // No ecclist system property, so use our own list. + if (useExactMatch) { + return (number.equals("112") || number.equals("911")); + } else { + return (number.startsWith("112") || number.startsWith("911")); + } } /** @@ -1559,31 +1620,81 @@ public class PhoneNumberUtils * @param defaultCountryIso the specific country which the number should be checked against * @return if the number is an emergency number for the specific country, then return true, * otherwise false + * * @hide */ public static boolean isEmergencyNumber(String number, String defaultCountryIso) { - PhoneNumberUtil util = PhoneNumberUtil.getInstance(); - try { - PhoneNumber pn = util.parse(number, defaultCountryIso); - // libphonenumber guarantees short numbers such as emergency numbers are classified as - // invalid. Therefore, if the number passes the validation test, we believe it is not an - // emergency number. - // TODO: Compare against a list of country-specific known emergency numbers instead, once - // that has been collected. - if (util.isValidNumber(pn)) { - return false; - } else if ("BR".equalsIgnoreCase(defaultCountryIso) && number.length() >= 8) { - // This is to prevent Brazilian local numbers which start with 911 being incorrectly - // classified as emergency numbers. 911 is not an emergency number in Brazil; it is also - // not possible to append additional digits to an emergency number to dial the number in - // Brazil - it won't connect. - // TODO: Clean this up once a list of country-specific known emergency numbers is - // collected. - return false; - } - } catch (NumberParseException e) { - } - return isEmergencyNumber(number); + return isEmergencyNumberInternal(number, + defaultCountryIso, + true /* useExactMatch */); + } + + /** + * Checks if a given number might *potentially* result in a call to an + * emergency service, for a specific country. + * + * Specifically, this method will return true if the specified number + * is an emergency number in the specified country, *or* if the number + * simply starts with the same digits as any emergency number for that + * country. + * + * This method is intended for internal use by the phone app when + * deciding whether to allow ACTION_CALL intents from 3rd party apps + * (where we're required to *not* allow emergency calls to be placed.) + * + * @param number the number to look up. + * @param defaultCountryIso the specific country which the number should be checked against + * @return true if the number is an emergency number for the specific + * country, *or* if the number starts with the same digits as + * any of those emergency numbers. + * + * @hide + */ + public static boolean isPotentialEmergencyNumber(String number, String defaultCountryIso) { + return isEmergencyNumberInternal(number, + defaultCountryIso, + false /* useExactMatch */); + } + + /** + * Helper function for isEmergencyNumber(String, String) and + * isPotentialEmergencyNumber(String, String). + * + * @param number the number to look up. + * @param defaultCountryIso the specific country which the number should be checked against + * @param useExactMatch if true, consider a number to be an emergency + * number only if it *exactly* matches a number listed in + * the RIL / SIM. If false, a number is considered to be an + * emergency number if it simply starts with the same digits + * as any of the emergency numbers listed in the RIL / SIM. + * + * @return true if the number is an emergency number for the specified country. + */ + private static boolean isEmergencyNumberInternal(String number, + String defaultCountryIso, + boolean useExactMatch) { + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); + try { + PhoneNumber pn = util.parse(number, defaultCountryIso); + // libphonenumber guarantees short numbers such as emergency numbers are classified as + // invalid. Therefore, if the number passes the validation test, we believe it is not an + // emergency number. + // TODO: Compare against a list of country-specific known emergency numbers instead, once + // that has been collected. + if (util.isValidNumber(pn)) { + return false; + } else if ("BR".equalsIgnoreCase(defaultCountryIso) && number.length() >= 8) { + // This is to prevent Brazilian local numbers which start with 911 being incorrectly + // classified as emergency numbers. 911 is not an emergency number in Brazil; it is also + // not possible to append additional digits to an emergency number to dial the number in + // Brazil - it won't connect. + // TODO: Clean this up once a list of country-specific known emergency numbers is + // collected. + return false; + } + } catch (NumberParseException e) { + } + return isEmergencyNumberInternal(number, useExactMatch); } /** @@ -1592,12 +1703,66 @@ public class PhoneNumberUtils * * @param number the number to look up. * @param context the specific context which the number should be checked against - * @return if a phone number is an emergency number for a local country, based on the - * CountryDetector. + * @return true if the specified number is an emergency number for a local country, based on the + * CountryDetector. + * * @see android.location.CountryDetector * @hide */ public static boolean isLocalEmergencyNumber(String number, Context context) { + return isLocalEmergencyNumberInternal(number, + context, + true /* useExactMatch */); + } + + /** + * Checks if a given number might *potentially* result in a call to an + * emergency service, for the country that the user is in. The current + * country is determined using the CountryDetector. + * + * Specifically, this method will return true if the specified number + * is an emergency number in the current country, *or* if the number + * simply starts with the same digits as any emergency number for the + * current country. + * + * This method is intended for internal use by the phone app when + * deciding whether to allow ACTION_CALL intents from 3rd party apps + * (where we're required to *not* allow emergency calls to be placed.) + * + * @param number the number to look up. + * @param context the specific context which the number should be checked against + * @return true if the specified number is an emergency number for a local country, based on the + * CountryDetector. + * + * @see android.location.CountryDetector + * @hide + */ + public static boolean isPotentialLocalEmergencyNumber(String number, Context context) { + return isLocalEmergencyNumberInternal(number, + context, + false /* useExactMatch */); + } + + /** + * Helper function for isLocalEmergencyNumber() and + * isPotentialLocalEmergencyNumber(). + * + * @param number the number to look up. + * @param context the specific context which the number should be checked against + * @param useExactMatch if true, consider a number to be an emergency + * number only if it *exactly* matches a number listed in + * the RIL / SIM. If false, a number is considered to be an + * emergency number if it simply starts with the same digits + * as any of the emergency numbers listed in the RIL / SIM. + * + * @return true if the specified number is an emergency number for a + * local country, based on the CountryDetector. + * + * @see android.location.CountryDetector + */ + private static boolean isLocalEmergencyNumberInternal(String number, + Context context, + boolean useExactMatch) { String countryIso; CountryDetector detector = (CountryDetector) context.getSystemService( Context.COUNTRY_DETECTOR); @@ -1609,7 +1774,7 @@ public class PhoneNumberUtils Log.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: " + countryIso); } - return isEmergencyNumber(number, countryIso); + return isEmergencyNumberInternal(number, countryIso, useExactMatch); } /** diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java index fc8a145fcd71..141074717c21 100644 --- a/telephony/java/android/telephony/SmsMessage.java +++ b/telephony/java/android/telephony/SmsMessage.java @@ -291,12 +291,31 @@ public class SmsMessage { // flexibly... int limit; - if (ted.msgCount > 1) { - limit = (ted.codeUnitSize == ENCODING_7BIT) ? - MAX_USER_DATA_SEPTETS_WITH_HEADER : MAX_USER_DATA_BYTES_WITH_HEADER; + if (ted.codeUnitSize == ENCODING_7BIT) { + int udhLength; + if (ted.languageTable != 0 && ted.languageShiftTable != 0) { + udhLength = GsmAlphabet.UDH_SEPTET_COST_TWO_SHIFT_TABLES; + } else if (ted.languageTable != 0 || ted.languageShiftTable != 0) { + udhLength = GsmAlphabet.UDH_SEPTET_COST_ONE_SHIFT_TABLE; + } else { + udhLength = 0; + } + + if (ted.msgCount > 1) { + udhLength += GsmAlphabet.UDH_SEPTET_COST_CONCATENATED_MESSAGE; + } + + if (udhLength != 0) { + udhLength += GsmAlphabet.UDH_SEPTET_COST_LENGTH; + } + + limit = MAX_USER_DATA_SEPTETS - udhLength; } else { - limit = (ted.codeUnitSize == ENCODING_7BIT) ? - MAX_USER_DATA_SEPTETS : MAX_USER_DATA_BYTES; + if (ted.msgCount > 1) { + limit = MAX_USER_DATA_BYTES_WITH_HEADER; + } else { + limit = MAX_USER_DATA_BYTES; + } } int pos = 0; // Index in code units. diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index 5b13603a924f..410e9614e9dd 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -167,7 +167,9 @@ public abstract class DataConnectionTracker extends Handler { // independent of mInternalDataEnabled and requests for APN access // persisted protected boolean mUserDataEnabled = true; - protected boolean mPolicyDataEnabled = true; + + // TODO: move away from static state once 5587429 is fixed. + protected static boolean sPolicyDataEnabled = true; private boolean[] dataEnabled = new boolean[APN_NUM_TYPES]; @@ -766,7 +768,7 @@ public abstract class DataConnectionTracker extends Handler { public boolean getAnyDataEnabled() { final boolean result; synchronized (mDataEnabledLock) { - result = (mInternalDataEnabled && mUserDataEnabled && mPolicyDataEnabled + result = (mInternalDataEnabled && mUserDataEnabled && sPolicyDataEnabled && (enabledCount != 0)); } if (!result && DBG) log("getAnyDataEnabled " + result); @@ -1132,8 +1134,8 @@ public abstract class DataConnectionTracker extends Handler { protected void onSetPolicyDataEnabled(boolean enabled) { synchronized (mDataEnabledLock) { final boolean prevEnabled = getAnyDataEnabled(); - if (mPolicyDataEnabled != enabled) { - mPolicyDataEnabled = enabled; + if (sPolicyDataEnabled != enabled) { + sPolicyDataEnabled = enabled; if (prevEnabled != getAnyDataEnabled()) { if (!prevEnabled) { resetAllRetryCounts(); diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java index 2e998490e875..25647ac8ad1f 100644 --- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java +++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java @@ -60,25 +60,25 @@ public class GsmAlphabet { * all combinations of header elements below will have at least one free bit * when padding to the nearest septet boundary. */ - private static final int UDH_SEPTET_COST_LENGTH = 1; + public static final int UDH_SEPTET_COST_LENGTH = 1; /** * Using a non-default language locking shift table OR single shift table * requires a user data header of 3 octets, or 4 septets, plus UDH length. */ - private static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; + public static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; /** * Using a non-default language locking shift table AND single shift table * requires a user data header of 6 octets, or 7 septets, plus UDH length. */ - private static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; + public static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; /** * Multi-part messages require a user data header of 5 octets, or 6 septets, * plus UDH length. */ - private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; + public static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; /** * Converts a char to a GSM 7 bit table index. diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 865caf63224c..7cd01a167d78 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -549,7 +549,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { @Override public boolean getAnyDataEnabled() { synchronized (mDataEnabledLock) { - if (!(mInternalDataEnabled && mUserDataEnabled && mPolicyDataEnabled)) return false; + if (!(mInternalDataEnabled && mUserDataEnabled && sPolicyDataEnabled)) return false; for (ApnContext apnContext : mApnContexts.values()) { // Make sure we dont have a context that going down // and is explicitly disabled. diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java index 41a719e1b64d..595066957435 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java @@ -16,11 +16,14 @@ package com.android.internal.telephony; +import android.telephony.TelephonyManager; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + import com.android.internal.telephony.gsm.SmsMessage; import com.android.internal.util.HexDump; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; +import java.util.ArrayList; public class GsmSmsTest extends AndroidTestCase { @@ -232,6 +235,110 @@ public class GsmSmsTest extends AndroidTestCase { }; @SmallTest + public void testFragmentText() throws Exception { + boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() == + TelephonyManager.PHONE_TYPE_GSM); + + // Valid 160 character 7-bit text. + String text = "123456789012345678901234567890123456789012345678901234567890" + + "1234567890123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890"; + SmsMessageBase.TextEncodingDetails ted = SmsMessage.calculateLength(text, false); + assertEquals(1, ted.msgCount); + assertEquals(160, ted.codeUnitCount); + assertEquals(1, ted.codeUnitSize); + assertEquals(0, ted.languageTable); + assertEquals(0, ted.languageShiftTable); + if (isGsmPhone) { + ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); + assertEquals(1, fragments.size()); + } + + // Valid 161 character 7-bit text. + text = "123456789012345678901234567890123456789012345678901234567890" + + "1234567890123456789012345678901234567890123456789012345678901234567890" + + "1234567890123456789012345678901"; + ted = SmsMessage.calculateLength(text, false); + assertEquals(2, ted.msgCount); + assertEquals(161, ted.codeUnitCount); + assertEquals(1, ted.codeUnitSize); + assertEquals(0, ted.languageTable); + assertEquals(0, ted.languageShiftTable); + if (isGsmPhone) { + ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); + assertEquals(2, fragments.size()); + assertEquals(text, fragments.get(0) + fragments.get(1)); + assertEquals(153, fragments.get(0).length()); + assertEquals(8, fragments.get(1).length()); + } + } + + @SmallTest + public void testFragmentTurkishText() throws Exception { + boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() == + TelephonyManager.PHONE_TYPE_GSM); + + int[] oldTables = GsmAlphabet.getEnabledSingleShiftTables(); + int[] turkishTable = { 1 }; + GsmAlphabet.setEnabledSingleShiftTables(turkishTable); + + // Valid 77 character text with Turkish characters. + String text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + + "ĞŞİğşıĞŞİğşıĞŞİğş"; + SmsMessageBase.TextEncodingDetails ted = SmsMessage.calculateLength(text, false); + assertEquals(1, ted.msgCount); + assertEquals(154, ted.codeUnitCount); + assertEquals(1, ted.codeUnitSize); + assertEquals(0, ted.languageTable); + assertEquals(1, ted.languageShiftTable); + if (isGsmPhone) { + ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); + assertEquals(1, fragments.size()); + assertEquals(text, fragments.get(0)); + assertEquals(77, fragments.get(0).length()); + } + + // Valid 78 character text with Turkish characters. + text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + + "ĞŞİğşıĞŞİğşıĞŞİğşı"; + ted = SmsMessage.calculateLength(text, false); + assertEquals(2, ted.msgCount); + assertEquals(156, ted.codeUnitCount); + assertEquals(1, ted.codeUnitSize); + assertEquals(0, ted.languageTable); + assertEquals(1, ted.languageShiftTable); + if (isGsmPhone) { + ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); + assertEquals(2, fragments.size()); + assertEquals(text, fragments.get(0) + fragments.get(1)); + assertEquals(74, fragments.get(0).length()); + assertEquals(4, fragments.get(1).length()); + } + + // Valid 160 character text with Turkish characters. + text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" + + "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğ" + + "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı"; + ted = SmsMessage.calculateLength(text, false); + assertEquals(3, ted.msgCount); + assertEquals(320, ted.codeUnitCount); + assertEquals(1, ted.codeUnitSize); + assertEquals(0, ted.languageTable); + assertEquals(1, ted.languageShiftTable); + if (isGsmPhone) { + ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text); + assertEquals(3, fragments.size()); + assertEquals(text, fragments.get(0) + fragments.get(1) + fragments.get(2)); + assertEquals(74, fragments.get(0).length()); + assertEquals(74, fragments.get(1).length()); + assertEquals(12, fragments.get(2).length()); + } + + GsmAlphabet.setEnabledSingleShiftTables(oldTables); + } + + + @SmallTest public void testDecode() throws Exception { decodeSingle(0); // default table decodeSingle(1); // Turkish locking shift table diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java index e2349afbf85e..d34a7c50b980 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java @@ -550,21 +550,51 @@ public class PhoneNumberUtilsTest extends AndroidTestCase { } @SmallTest public void testIsEmergencyNumber() { - assertTrue(PhoneNumberUtils.isEmergencyNumber("911", "US")); - assertTrue(PhoneNumberUtils.isEmergencyNumber("112", "US")); - // The next two numbers are not valid phone numbers in the US, but can be used to trick the - // system to dial 911 and 112, which are emergency numbers in the US. For the purpose of - // addressing that, they are also classified as emergency numbers in the US. - assertTrue(PhoneNumberUtils.isEmergencyNumber("91112345", "US")); - assertTrue(PhoneNumberUtils.isEmergencyNumber("11212345", "US")); - // A valid mobile phone number from Singapore shouldn't be classified as an emergency number - // in Singapore, as 911 is not an emergency number there. - assertFalse(PhoneNumberUtils.isEmergencyNumber("91121234", "SG")); - // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number - // in Brazil, as 112 is not an emergency number there. - assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR")); - // A valid local phone number from Brazil shouldn't be classified as an emergency number in - // Brazil. - assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "BR")); + // There are two parallel sets of tests here: one for the + // regular isEmergencyNumber() method, and the other for + // isPotentialEmergencyNumber(). + // + // (The difference is that isEmergencyNumber() will return true + // only if the specified number exactly matches an actual + // emergency number, but isPotentialEmergencyNumber() will + // return true if the specified number simply starts with the + // same digits as any actual emergency number.) + + // Tests for isEmergencyNumber(): + assertTrue(PhoneNumberUtils.isEmergencyNumber("911", "US")); + assertTrue(PhoneNumberUtils.isEmergencyNumber("112", "US")); + // The next two numbers are not valid phone numbers in the US, + // so do not count as emergency numbers (but they *are* "potential" + // emergency numbers; see below.) + assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "US")); + assertFalse(PhoneNumberUtils.isEmergencyNumber("11212345", "US")); + // A valid mobile phone number from Singapore shouldn't be classified as an emergency number + // in Singapore, as 911 is not an emergency number there. + assertFalse(PhoneNumberUtils.isEmergencyNumber("91121234", "SG")); + // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number + // in Brazil, as 112 is not an emergency number there. + assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR")); + // A valid local phone number from Brazil shouldn't be classified as an emergency number in + // Brazil. + assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "BR")); + + // Tests for isPotentialEmergencyNumber(): + // These first two are obviously emergency numbers: + assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("911", "US")); + assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("112", "US")); + // The next two numbers are not valid phone numbers in the US, but can be used to trick the + // system to dial 911 and 112, which are emergency numbers in the US. For the purpose of + // addressing that, they are also classified as "potential" emergency numbers in the US. + assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("91112345", "US")); + assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("11212345", "US")); + // A valid mobile phone number from Singapore shouldn't be classified as an emergency number + // in Singapore, as 911 is not an emergency number there. + assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("91121234", "SG")); + // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number + // in Brazil, as 112 is not an emergency number there. + assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("1121234567", "BR")); + // A valid local phone number from Brazil shouldn't be classified as an emergency number in + // Brazil. + assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("91112345", "BR")); } } diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java index 22eb5794230d..175f227f7e0f 100644 --- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java +++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -45,6 +46,7 @@ import java.util.ArrayList; public class FrameworkPerfActivity extends Activity implements AdapterView.OnItemSelectedListener { static final String TAG = "Perf"; + static final boolean DEBUG = false; Spinner mFgSpinner; Spinner mBgSpinner; @@ -67,22 +69,47 @@ public class FrameworkPerfActivity extends Activity TestService.Op mBgTest; int mCurOpIndex = 0; TestConnection mCurConnection; + boolean mConnectionBound; final ArrayList<RunResult> mResults = new ArrayList<RunResult>(); - class TestConnection implements ServiceConnection { + class TestConnection implements ServiceConnection, IBinder.DeathRecipient { Messenger mService; + boolean mLinked; @Override public void onServiceConnected(ComponentName name, IBinder service) { - mService = new Messenger(service); - dispatchCurOp(this); + try { + if (!(service instanceof Binder)) { + // If remote, we'll be killing ye. + service.linkToDeath(this, 0); + mLinked = true; + } + mService = new Messenger(service); + dispatchCurOp(this); + } catch (RemoteException e) { + // Whoops, service has disappeared... try starting again. + Log.w(TAG, "Test service died, starting again"); + startCurOp(); + } } @Override public void onServiceDisconnected(ComponentName name) { } + + @Override public void binderDied() { + cleanup(); + connectionDied(this); + } + + void cleanup() { + if (mLinked) { + mLinked = false; + mService.getBinder().unlinkToDeath(this, 0); + } + } } - static final int MSG_CONTINUE = 1000; + static final int MSG_DO_NEXT_TEST = 1000; final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -93,11 +120,7 @@ public class FrameworkPerfActivity extends Activity RunResult res = (RunResult)bundle.getParcelable("res"); completeCurOp(res); } break; - case TestService.RES_TERMINATED: { - // Give a little time for things to settle down. - sendMessageDelayed(obtainMessage(MSG_CONTINUE), 500); - } break; - case MSG_CONTINUE: { + case MSG_DO_NEXT_TEST: { startCurOp(); } break; } @@ -235,7 +258,7 @@ public class FrameworkPerfActivity extends Activity try { conn.mService.send(msg); } catch (RemoteException e) { - Log.i(TAG, "Failure communicating with service", e); + Log.w(TAG, "Failure communicating with service", e); } } @@ -273,29 +296,55 @@ public class FrameworkPerfActivity extends Activity } void disconnect() { - if (mCurConnection != null) { - unbindService(mCurConnection); - if (mCurConnection.mService != null) { + final TestConnection conn = mCurConnection; + if (conn != null) { + if (DEBUG) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Log.i(TAG, "Unbinding " + conn, here); + } + if (mConnectionBound) { + unbindService(conn); + mConnectionBound = false; + } + if (conn.mLinked) { Message msg = Message.obtain(null, TestService.CMD_TERMINATE); - msg.replyTo = mMessenger; try { - mCurConnection.mService.send(msg); + conn.mService.send(msg); + return; } catch (RemoteException e) { - Log.i(TAG, "Failure communicating with service", e); + Log.w(TAG, "Test service aleady died when terminating"); } } + conn.cleanup(); + } + connectionDied(conn); + } + + void connectionDied(TestConnection conn) { + if (mCurConnection == conn) { + // Now that we know the test process has died, we can commence + // the next test. Just give a little delay to allow the activity + // manager to know it has died as well (not a disaster if it hasn't + // yet, though). + if (mConnectionBound) { + unbindService(conn); + } mCurConnection = null; + mHandler.sendMessageDelayed(Message.obtain(null, MSG_DO_NEXT_TEST), 100); } } void startCurOp() { + if (DEBUG) Log.i(TAG, "startCurOp: mCurConnection=" + mCurConnection); if (mCurConnection != null) { disconnect(); + return; } if (mStarted) { mHandler.removeMessages(TestService.RES_TEST_FINISHED); mHandler.removeMessages(TestService.RES_TERMINATED); - mHandler.removeMessages(MSG_CONTINUE); + mHandler.removeMessages(MSG_DO_NEXT_TEST); mCurConnection = new TestConnection(); Intent intent; if (mLocalCheckBox.isChecked()) { @@ -303,7 +352,13 @@ public class FrameworkPerfActivity extends Activity } else { intent = new Intent(this, TestService.class); } + if (DEBUG) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Log.i(TAG, "Binding " + mCurConnection, here); + } bindService(intent, mCurConnection, BIND_AUTO_CREATE|BIND_IMPORTANT); + mConnectionBound = true; } } diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java index ce27b65e8fd1..3d939bdf6a80 100644 --- a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java +++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java @@ -138,7 +138,10 @@ public class TestService extends Service { static final int CMD_START_TEST = 1; static final int CMD_TERMINATE = 2; - + + static final int MSG_REALLY_START = 1000; + static final int MSG_REALLY_TERMINATE = 1001; + static final int RES_TEST_FINISHED = 1; static final int RES_TERMINATED = 2; @@ -146,6 +149,13 @@ public class TestService extends Service { @Override public void handleMessage(Message msg) { switch (msg.what) { case CMD_START_TEST: { + // Give a little time for things to settle down. + Message newMsg = Message.obtain(null, MSG_REALLY_START); + newMsg.obj = msg.obj; + newMsg.replyTo = msg.replyTo; + sendMessageDelayed(newMsg, 500); + } break; + case MSG_REALLY_START: { Bundle bundle = (Bundle)msg.obj; bundle.setClassLoader(getClassLoader()); final TestArgs args = (TestArgs)bundle.getParcelable("args"); @@ -166,6 +176,13 @@ public class TestService extends Service { }); } break; case CMD_TERMINATE: { + // Give a little time for things to settle down. + Message newMsg = Message.obtain(null, MSG_REALLY_TERMINATE); + newMsg.obj = msg.obj; + newMsg.replyTo = msg.replyTo; + sendMessageDelayed(newMsg, 50); + } break; + case MSG_REALLY_TERMINATE: { if (msg.replyTo != null) { Message reply = Message.obtain(null, RES_TERMINATED); try { @@ -174,7 +191,7 @@ public class TestService extends Service { } } terminate(); - } + } break; } } }; @@ -187,7 +204,7 @@ public class TestService extends Service { } void terminate() { - Process.killProcess(Process.myPid()); + Runtime.getRuntime().exit(0); } enum BackgroundMode { diff --git a/wifi/java/android/net/wifi/WifiApConfigStore.java b/wifi/java/android/net/wifi/WifiApConfigStore.java index bb5427d01879..0531ca376149 100644 --- a/wifi/java/android/net/wifi/WifiApConfigStore.java +++ b/wifi/java/android/net/wifi/WifiApConfigStore.java @@ -19,11 +19,16 @@ package android.net.wifi; import android.content.Context; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.os.Environment; -import android.os.Message; import android.os.Handler; -import android.os.HandlerThread; +import android.os.Message; +import android.os.Messenger; import android.util.Log; +import com.android.internal.util.AsyncChannel; +import com.android.internal.R; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; @@ -34,16 +39,13 @@ import java.io.IOException; import java.net.InetAddress; import java.util.UUID; -import com.android.internal.R; - - /** * Provides API to the WifiStateMachine for doing read/write access * to soft access point configuration */ -class WifiApConfigStore { +class WifiApConfigStore extends StateMachine { - private static Context sContext; + private Context mContext; private static final String TAG = "WifiApConfigStore"; private static final String AP_CONFIG_FILE = Environment.getDataDirectory() + @@ -51,131 +53,160 @@ class WifiApConfigStore { private static final int AP_CONFIG_FILE_VERSION = 1; - private static WifiConfiguration sApConfig = new WifiConfiguration(); - private static final Object sApConfigLock = new Object(); + private State mDefaultState = new DefaultState(); + private State mInactiveState = new InactiveState(); + private State mActiveState = new ActiveState(); + + private WifiConfiguration mWifiApConfig = null; + private AsyncChannel mReplyChannel = new AsyncChannel(); - private static FileReadWriteHandler sFileReadWriteHandler; - private static final int READ_AP_CONFIG = 1; - private static final int WRITE_AP_CONFIG = 2; + WifiApConfigStore(Context context, Handler target) { + super(TAG, target.getLooper()); - static void initialize(Context context) { - sContext = context; + mContext = context; + addState(mDefaultState); + addState(mInactiveState, mDefaultState); + addState(mActiveState, mDefaultState); - /* File operations happen on a seperate thread */ - HandlerThread configThread = new HandlerThread("WifiApConfigStore"); - configThread.start(); - sFileReadWriteHandler = new FileReadWriteHandler(configThread.getLooper()); - Message.obtain(sFileReadWriteHandler, READ_AP_CONFIG).sendToTarget(); + setInitialState(mInactiveState); } + public static WifiApConfigStore makeWifiApConfigStore(Context context, Handler target) { + WifiApConfigStore s = new WifiApConfigStore(context, target); + s.start(); + return s; + } - static void setApConfiguration(WifiConfiguration config) { - synchronized (sApConfigLock) { - sApConfig = config; + class DefaultState extends State { + public boolean processMessage(Message message) { + switch (message.what) { + case WifiStateMachine.CMD_SET_AP_CONFIG: + case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED: + Log.e(TAG, "Unexpected message: " + message); + break; + case WifiStateMachine.CMD_REQUEST_AP_CONFIG: + mReplyChannel.replyToMessage(message, + WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig); + break; + default: + Log.e(TAG, "Failed to handle " + message); + break; + } + return HANDLED; } - Message.obtain(sFileReadWriteHandler, WRITE_AP_CONFIG, new WifiConfiguration(config)) - .sendToTarget(); } - static WifiConfiguration getApConfiguration() { - synchronized (sApConfigLock) { - return new WifiConfiguration(sApConfig); + class InactiveState extends State { + public boolean processMessage(Message message) { + switch (message.what) { + case WifiStateMachine.CMD_SET_AP_CONFIG: + mWifiApConfig = (WifiConfiguration) message.obj; + transitionTo(mActiveState); + break; + default: + return NOT_HANDLED; + } + return HANDLED; } } - /** - * File read/write handler - */ - private static class FileReadWriteHandler extends Handler { - - public FileReadWriteHandler(android.os.Looper looper) { - super(looper); + class ActiveState extends State { + public void enter() { + new Thread(new Runnable() { + public void run() { + writeApConfiguration(mWifiApConfig); + sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED); + } + }).start(); } - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case WRITE_AP_CONFIG: - writeApConfiguration((WifiConfiguration) msg.obj); + public boolean processMessage(Message message) { + switch (message.what) { + //TODO: have feedback to the user when we do this + //to indicate the write is currently in progress + case WifiStateMachine.CMD_SET_AP_CONFIG: + deferMessage(message); break; - case READ_AP_CONFIG: - readApConfiguration(); + case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED: + transitionTo(mInactiveState); break; default: - Log.e(TAG, "Unknown command in FileReadWriteHandler: " + msg); - break; + return NOT_HANDLED; } + return HANDLED; } + } - private static void writeApConfiguration(final WifiConfiguration config) { - DataOutputStream out = null; - try { - out = new DataOutputStream(new BufferedOutputStream( - new FileOutputStream(AP_CONFIG_FILE))); - - out.writeInt(AP_CONFIG_FILE_VERSION); - out.writeUTF(config.SSID); - int authType = config.getAuthType(); - out.writeInt(authType); - if(authType != KeyMgmt.NONE) { - out.writeUTF(config.preSharedKey); - } - } catch (IOException e) { - Log.e(TAG, "Error writing hotspot configuration" + e); - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) {} - } - } - } + void loadApConfiguration() { + DataInputStream in = null; + try { + WifiConfiguration config = new WifiConfiguration(); + in = new DataInputStream(new BufferedInputStream(new FileInputStream( + AP_CONFIG_FILE))); - private static void readApConfiguration() { - DataInputStream in = null; - try { - WifiConfiguration config = new WifiConfiguration(); - in = new DataInputStream(new BufferedInputStream(new FileInputStream( - AP_CONFIG_FILE))); - - int version = in.readInt(); - if (version != 1) { - Log.e(TAG, "Bad version on hotspot configuration file, set defaults"); - setDefaultApConfiguration(); - return; - } - config.SSID = in.readUTF(); - int authType = in.readInt(); - config.allowedKeyManagement.set(authType); - if (authType != KeyMgmt.NONE) { - config.preSharedKey = in.readUTF(); - } - synchronized (sApConfigLock) { - sApConfig = config; - } - } catch (IOException ignore) { + int version = in.readInt(); + if (version != 1) { + Log.e(TAG, "Bad version on hotspot configuration file, set defaults"); setDefaultApConfiguration(); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) {} - } + return; + } + config.SSID = in.readUTF(); + int authType = in.readInt(); + config.allowedKeyManagement.set(authType); + if (authType != KeyMgmt.NONE) { + config.preSharedKey = in.readUTF(); + } + mWifiApConfig = config; + } catch (IOException ignore) { + setDefaultApConfiguration(); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) {} } } + } - /* Generate a default WPA2 based configuration with a random password. - We are changing the Wifi Ap configuration storage from secure settings to a - flat file accessible only by the system. A WPA2 based default configuration - will keep the device secure after the update */ - private static void setDefaultApConfiguration() { - WifiConfiguration config = new WifiConfiguration(); - config.SSID = sContext.getString(R.string.wifi_tether_configure_ssid_default); - config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK); - String randomUUID = UUID.randomUUID().toString(); - //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx - config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13); - setApConfiguration(config); + Messenger getMessenger() { + return new Messenger(getHandler()); + } + + private void writeApConfiguration(final WifiConfiguration config) { + DataOutputStream out = null; + try { + out = new DataOutputStream(new BufferedOutputStream( + new FileOutputStream(AP_CONFIG_FILE))); + + out.writeInt(AP_CONFIG_FILE_VERSION); + out.writeUTF(config.SSID); + int authType = config.getAuthType(); + out.writeInt(authType); + if(authType != KeyMgmt.NONE) { + out.writeUTF(config.preSharedKey); + } + } catch (IOException e) { + Log.e(TAG, "Error writing hotspot configuration" + e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) {} + } } } + + /* Generate a default WPA2 based configuration with a random password. + We are changing the Wifi Ap configuration storage from secure settings to a + flat file accessible only by the system. A WPA2 based default configuration + will keep the device secure after the update */ + private void setDefaultApConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default); + config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK); + String randomUUID = UUID.randomUUID().toString(); + //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx + config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13); + sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG, config); + } } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 00fae2ee2ddb..aadcaadaa663 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -184,6 +184,7 @@ public class WifiStateMachine extends StateMachine { private WifiP2pManager mWifiP2pManager; //Used to initiate a connection with WifiP2pService private AsyncChannel mWifiP2pChannel = new AsyncChannel(); + private AsyncChannel mWifiApConfigChannel = new AsyncChannel(); // Event log tags (must be in sync with event-log-tags) private static final int EVENTLOG_WIFI_STATE_CHANGED = 50021; @@ -233,12 +234,16 @@ public class WifiStateMachine extends StateMachine { static final int CMD_STOP_AP = BASE + 24; /* Set the soft access point configuration */ static final int CMD_SET_AP_CONFIG = BASE + 25; - /* Get the soft access point configuration */ - static final int CMD_GET_AP_CONFIG = BASE + 26; + /* Soft access point configuration set completed */ + static final int CMD_SET_AP_CONFIG_COMPLETED = BASE + 26; + /* Request the soft access point configuration */ + static final int CMD_REQUEST_AP_CONFIG = BASE + 27; + /* Response to access point configuration request */ + static final int CMD_RESPONSE_AP_CONFIG = BASE + 28; /* Set configuration on tether interface */ - static final int CMD_TETHER_INTERFACE = BASE + 27; + static final int CMD_TETHER_INTERFACE = BASE + 29; - static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 28; + static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 30; /* Supplicant commands */ /* Is supplicant alive ? */ @@ -530,6 +535,11 @@ public class WifiStateMachine extends StateMachine { mWpsStateMachine = new WpsStateMachine(context, this, getHandler()); mLinkProperties = new LinkProperties(); + WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore( + context, getHandler()); + wifiApConfigStore.loadApConfiguration(); + mWifiApConfigChannel.connectSync(mContext, getHandler(), wifiApConfigStore.getMessenger()); + mNetworkInfo.setIsAvailable(false); mLinkProperties.clear(); mLastBssid = null; @@ -659,11 +669,11 @@ public class WifiStateMachine extends StateMachine { } public void setWifiApConfiguration(WifiConfiguration config) { - sendMessage(obtainMessage(CMD_SET_AP_CONFIG, config)); + mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config); } - public WifiConfiguration syncGetWifiApConfiguration(AsyncChannel channel) { - Message resultMsg = channel.sendMessageSynchronously(CMD_GET_AP_CONFIG); + public WifiConfiguration syncGetWifiApConfiguration() { + Message resultMsg = mWifiApConfigChannel.sendMessageSynchronously(CMD_REQUEST_AP_CONFIG); WifiConfiguration ret = (WifiConfiguration) resultMsg.obj; resultMsg.recycle(); return ret; @@ -1714,25 +1724,27 @@ public class WifiStateMachine extends StateMachine { * TODO: Add control channel setup through hostapd that allows changing config * on a running daemon */ - private boolean startSoftApWithConfig(WifiConfiguration config) { - if (config == null) { - config = WifiApConfigStore.getApConfiguration(); - } else { - WifiApConfigStore.setApConfiguration(config); - } - try { - mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); - } catch (Exception e) { - loge("Exception in softap start " + e); - try { - mNwService.stopAccessPoint(mInterfaceName); - mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); - } catch (Exception e1) { - loge("Exception in softap re-start " + e1); - return false; + private void startSoftApWithConfig(final WifiConfiguration config) { + // start hostapd on a seperate thread + new Thread(new Runnable() { + public void run() { + try { + mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); + } catch (Exception e) { + loge("Exception in softap start " + e); + try { + mNwService.stopAccessPoint(mInterfaceName); + mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); + } catch (Exception e1) { + loge("Exception in softap re-start " + e1); + sendMessage(CMD_START_AP_FAILURE); + return; + } + } + if (DBG) log("Soft AP start successful"); + sendMessage(CMD_START_AP_SUCCESS); } - } - return true; + }).start(); } /******************************************************** @@ -1775,13 +1787,6 @@ public class WifiStateMachine extends StateMachine { case CMD_ENABLE_BACKGROUND_SCAN: mEnableBackgroundScan = (message.arg1 == 1); break; - case CMD_SET_AP_CONFIG: - WifiApConfigStore.setApConfiguration((WifiConfiguration) message.obj); - break; - case CMD_GET_AP_CONFIG: - WifiConfiguration config = WifiApConfigStore.getApConfiguration(); - mReplyChannel.replyToMessage(message, message.what, config); - break; /* Discard */ case CMD_LOAD_DRIVER: case CMD_UNLOAD_DRIVER: @@ -1823,6 +1828,11 @@ public class WifiStateMachine extends StateMachine { case CMD_ENABLE_ALL_NETWORKS: case DhcpStateMachine.CMD_PRE_DHCP_ACTION: case DhcpStateMachine.CMD_POST_DHCP_ACTION: + /* Handled by WifiApConfigStore */ + case CMD_SET_AP_CONFIG: + case CMD_SET_AP_CONFIG_COMPLETED: + case CMD_REQUEST_AP_CONFIG: + case CMD_RESPONSE_AP_CONFIG: break; case WifiMonitor.DRIVER_HUNG_EVENT: setWifiEnabled(false); @@ -1856,8 +1866,6 @@ public class WifiStateMachine extends StateMachine { // 50021 wifi_state_changed (custom|1|5) EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); - WifiApConfigStore.initialize(mContext); - if (WifiNative.isDriverLoaded()) { transitionTo(mDriverLoadedState); } @@ -3243,21 +3251,19 @@ public class WifiStateMachine extends StateMachine { if (DBG) log(getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); - final Message message = Message.obtain(getCurrentMessage()); - final WifiConfiguration config = (WifiConfiguration) message.obj; + final Message message = getCurrentMessage(); + if (message.what == CMD_START_AP) { + final WifiConfiguration config = (WifiConfiguration) message.obj; - // start hostapd on a seperate thread - new Thread(new Runnable() { - public void run() { - if (startSoftApWithConfig(config)) { - if (DBG) log("Soft AP start successful"); - sendMessage(CMD_START_AP_SUCCESS); - } else { - loge("Soft AP start failed"); - sendMessage(CMD_START_AP_FAILURE); - } + if (config == null) { + mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG); + } else { + mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config); + startSoftApWithConfig(config); } - }).start(); + } else { + throw new RuntimeException("Illegal transition to SoftApStartingState: " + message); + } } @Override public boolean processMessage(Message message) { @@ -3282,6 +3288,15 @@ public class WifiStateMachine extends StateMachine { case WifiP2pService.P2P_ENABLE_PENDING: deferMessage(message); break; + case WifiStateMachine.CMD_RESPONSE_AP_CONFIG: + WifiConfiguration config = (WifiConfiguration) message.obj; + if (config != null) { + startSoftApWithConfig(config); + } else { + loge("Softap config is null!"); + sendMessage(CMD_START_AP_FAILURE); + } + break; case CMD_START_AP_SUCCESS: setWifiApState(WIFI_AP_STATE_ENABLED); transitionTo(mSoftApStartedState); |