Merge "Don't recycle action button views" into klp-dev
diff --git a/Android.mk b/Android.mk
index 7ba8ddc..14d1a02 100644
--- a/Android.mk
+++ b/Android.mk
@@ -265,6 +265,8 @@
wifi/java/android/net/wifi/IWifiManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
+ packages/services/Proxy/com/android/net/IProxyCallback.aidl \
+ packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
# FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
diff --git a/api/current.txt b/api/current.txt
index ac3948f..fab32e8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10822,7 +10822,6 @@
method public abstract void setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException;
method public abstract void waitUntilIdle() throws android.hardware.camera2.CameraAccessException;
- field public static final int TEMPLATE_MANUAL = 5; // 0x5
field public static final int TEMPLATE_PREVIEW = 1; // 0x1
field public static final int TEMPLATE_RECORD = 3; // 0x3
field public static final int TEMPLATE_STILL_CAPTURE = 2; // 0x2
@@ -17974,6 +17973,7 @@
method public static boolean isExternalStorageRemovable();
field public static java.lang.String DIRECTORY_ALARMS;
field public static java.lang.String DIRECTORY_DCIM;
+ field public static java.lang.String DIRECTORY_DOCUMENTS;
field public static java.lang.String DIRECTORY_DOWNLOADS;
field public static java.lang.String DIRECTORY_MOVIES;
field public static java.lang.String DIRECTORY_MUSIC;
@@ -20811,10 +20811,10 @@
field public static final java.lang.String COLUMN_MIME_TYPE = "mime_type";
field public static final java.lang.String COLUMN_SIZE = "_size";
field public static final java.lang.String COLUMN_SUMMARY = "summary";
- field public static final int FLAG_DIR_PREFERS_GRID = 32; // 0x20
- field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 64; // 0x40
+ field public static final int FLAG_DIR_HIDE_GRID_TITLES = 64; // 0x40
+ field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
+ field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
- field public static final int FLAG_DIR_SUPPORTS_SEARCH = 16; // 0x10
field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
@@ -20832,9 +20832,11 @@
field public static final java.lang.String COLUMN_SUMMARY = "summary";
field public static final java.lang.String COLUMN_TITLE = "title";
field public static final int FLAG_ADVANCED = 4; // 0x4
+ field public static final int FLAG_EMPTY = 32; // 0x20
field public static final int FLAG_LOCAL_ONLY = 2; // 0x2
field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1
field public static final int FLAG_SUPPORTS_RECENTS = 8; // 0x8
+ field public static final int FLAG_SUPPORTS_SEARCH = 16; // 0x10
field public static final int ROOT_TYPE_DEVICE = 3; // 0x3
field public static final int ROOT_TYPE_SERVICE = 1; // 0x1
field public static final int ROOT_TYPE_SHORTCUT = 2; // 0x2
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index e522b78..55c66726 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1251,6 +1251,16 @@
}
@Override
+ public ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
+ try {
+ return mPM.getHomeActivities(outActivities);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ return null;
+ }
+
+ @Override
public void setComponentEnabledSetting(ComponentName componentName,
int newState, int flags) {
try {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 676fd1f..2172a7b 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -27,7 +27,6 @@
import android.os.ServiceManager;
import android.util.Log;
import android.util.Pair;
-
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -51,7 +50,7 @@
* devices, and start a scan for Bluetooth LE devices.
*
* <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
- * adapter, when running on JELLY_BEAN_MR1 and below, call the
+ * adapter, when running on JELLY_BEAN_MR1 and below, call the
* static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
* higher, retrieve it through
* {@link android.content.Context#getSystemService} with
@@ -1229,6 +1228,9 @@
} else if (profile == BluetoothProfile.HEALTH) {
BluetoothHealth health = new BluetoothHealth(context, listener);
return true;
+ } else if (profile == BluetoothProfile.MAP) {
+ BluetoothMap map = new BluetoothMap(context, listener);
+ return true;
} else {
return false;
}
@@ -1277,6 +1279,10 @@
BluetoothGattServer gattServer = (BluetoothGattServer)proxy;
gattServer.close();
break;
+ case BluetoothProfile.MAP:
+ BluetoothMap map = (BluetoothMap)proxy;
+ map.close();
+ break;
}
}
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 7de309f..fac8fd5 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import java.util.List;
+import java.util.ArrayList;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -30,25 +32,14 @@
* Profile.
*@hide
*/
-public class BluetoothMap {
+public final class BluetoothMap implements BluetoothProfile {
private static final String TAG = "BluetoothMap";
private static final boolean DBG = true;
private static final boolean VDBG = false;
- /** int extra for MAP_STATE_CHANGED_ACTION */
- public static final String MAP_STATE =
- "android.bluetooth.map.intent.MAP_STATE";
- /** int extra for MAP_STATE_CHANGED_ACTION */
- public static final String MAP_PREVIOUS_STATE =
- "android.bluetooth.map.intent.MAP_PREVIOUS_STATE";
-
- /** Indicates the state of a Map connection state has changed.
- * This intent will always contain MAP_STATE, MAP_PREVIOUS_STATE and
- * BluetoothIntent.ADDRESS extras.
- */
- public static final String MAP_STATE_CHANGED_ACTION =
- "android.bluetooth.map.intent.action.MAP_STATE_CHANGED";
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
private IBluetoothMap mService;
private final Context mContext;
@@ -57,41 +48,12 @@
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
- /** No client currently connected */
- public static final int STATE_DISCONNECTED = 0;
- /** Connection attempt in progress */
- public static final int STATE_CONNECTING = 1;
- /** Client is currently connected */
- public static final int STATE_CONNECTED = 2;
public static final int RESULT_FAILURE = 0;
public static final int RESULT_SUCCESS = 1;
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
- /**
- * An interface for notifying Bluetooth PCE IPC clients when they have
- * been connected to the BluetoothMap service.
- */
- public interface ServiceListener {
- /**
- * Called to notify the client when this proxy object has been
- * connected to the BluetoothMap service. Clients must wait for
- * this callback before making IPC calls on the BluetoothMap
- * service.
- */
- public void onServiceConnected(BluetoothMap proxy);
-
- /**
- * Called to notify the client that this proxy object has been
- * disconnected from the BluetoothMap service. Clients must not
- * make IPC calls on the BluetoothMap service after this callback.
- * This callback will currently only occur if the application hosting
- * the BluetoothMap service, but may be called more often in future.
- */
- public void onServiceDisconnected();
- }
-
final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
@@ -111,11 +73,7 @@
try {
if (mService == null) {
if (VDBG) Log.d(TAG,"Binding service...");
- if (!mContext.bindService(
- new Intent(IBluetoothMap.class.getName()),
- mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth MAP Service");
- }
+ doBind();
}
} catch (Exception re) {
Log.e(TAG,"",re);
@@ -128,7 +86,8 @@
/**
* Create a BluetoothMap proxy object.
*/
- public BluetoothMap(Context context, ServiceListener l) {
+ /*package*/ BluetoothMap(Context context, ServiceListener l) {
+ if (DBG) Log.d(TAG, "Create BluetoothMap proxy object");
mContext = context;
mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -140,9 +99,18 @@
Log.e(TAG,"",e);
}
}
- if (!context.bindService(new Intent(IBluetoothMap.class.getName()), mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth Map Service");
+ doBind();
+ }
+
+ boolean doBind() {
+ Intent intent = new Intent(IBluetoothMap.class.getName());
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindService(intent, mConnection, 0)) {
+ Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent);
+ return false;
}
+ return true;
}
protected void finalize() throws Throwable {
@@ -221,9 +189,9 @@
}
/**
- * Returns true if the specified Bluetooth device is connected (does not
- * include connecting). Returns false if not connected, or if this proxy
- * object is not currently connected to the Map service.
+ * Returns true if the specified Bluetooth device is connected.
+ * Returns false if not connected, or if this proxy object is not
+ * currently connected to the Map service.
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
@@ -239,21 +207,33 @@
}
/**
- * Disconnects the current Map Client. Currently this call blocks,
- * it may soon be made asynchronous. Returns false if this proxy object is
- * not currently connected to the Map service.
+ * Initiate connection. Initiation of outgoing connections is not
+ * supported for MAP server.
*/
- public boolean disconnect() {
- if (DBG) log("disconnect()");
- if (mService != null) {
+ public boolean connect(BluetoothDevice device) {
+ if (DBG) log("connect(" + device + ")" + "not supported for MAPS");
+ return false;
+ }
+
+ /**
+ * Initiate disconnect.
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on error,
+ * true otherwise
+ */
+ public boolean disconnect(BluetoothDevice device) {
+ if (DBG) log("disconnect(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
try {
- mService.disconnect();
- return true;
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
+ return mService.disconnect(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return false;
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -277,19 +257,132 @@
}
}
+ /**
+ * Get the list of connected devices. Currently at most one.
+ *
+ * @return list of connected devices
+ */
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (DBG) log("getConnectedDevices()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * Get the list of devices matching specified states. Currently at most one.
+ *
+ * @return list of matching devices
+ */
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (DBG) log("getDevicesMatchingStates()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * Get connection state of device
+ *
+ * @return device connection state
+ */
+ public int getConnectionState(BluetoothDevice device) {
+ if (DBG) log("getConnectionState(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ /**
+ * Set priority of the profile
+ *
+ * <p> The device should already be paired.
+ * Priority can be one of {@link #PRIORITY_ON} or
+ * {@link #PRIORITY_OFF},
+ *
+ * @param device Paired bluetooth device
+ * @param priority
+ * @return true if priority is set, false on error
+ */
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ if (priority != BluetoothProfile.PRIORITY_OFF &&
+ priority != BluetoothProfile.PRIORITY_ON) {
+ return false;
+ }
+ try {
+ return mService.setPriority(device, priority);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Get the priority of the profile.
+ *
+ * <p> The priority can be any of:
+ * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
+ * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ *
+ * @param device Bluetooth device
+ * @return priority of the device
+ */
+ public int getPriority(BluetoothDevice device) {
+ if (VDBG) log("getPriority(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getPriority(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return PRIORITY_OFF;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return PRIORITY_OFF;
+ }
+
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) log("Proxy object connected");
mService = IBluetoothMap.Stub.asInterface(service);
if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothMap.this);
+ mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) log("Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected();
+ mServiceListener.onServiceDisconnected(BluetoothProfile.MAP);
}
}
};
@@ -297,4 +390,19 @@
private static void log(String msg) {
Log.d(TAG, msg);
}
+
+ private boolean isEnabled() {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ log("Bluetooth is Not enabled");
+ return false;
+ }
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+
}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 6609b98..abdf949e 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -67,13 +67,16 @@
public static final ParcelUuid PBAP_PSE =
ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB");
public static final ParcelUuid MAP =
- ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
+ ParcelUuid.fromString("00001134-0000-1000-8000-00805F9B34FB");
public static final ParcelUuid MNS =
ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid MAS =
+ ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
+
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
- ObexObjectPush, PANU, NAP, MAP, MNS};
+ ObexObjectPush, PANU, NAP, MAP, MNS, MAS};
public static boolean isAudioSource(ParcelUuid uuid) {
return uuid.equals(AudioSource);
@@ -124,6 +127,9 @@
public static boolean isMns(ParcelUuid uuid) {
return uuid.equals(MNS);
}
+ public static boolean isMas(ParcelUuid uuid) {
+ return uuid.equals(MAS);
+ }
/**
* Returns true if ParcelUuid is present in uuidArray
diff --git a/core/java/android/bluetooth/IBluetoothMap.aidl b/core/java/android/bluetooth/IBluetoothMap.aidl
index 0c18e06..d4af63d 100644
--- a/core/java/android/bluetooth/IBluetoothMap.aidl
+++ b/core/java/android/bluetooth/IBluetoothMap.aidl
@@ -27,6 +27,11 @@
int getState();
BluetoothDevice getClient();
boolean connect(in BluetoothDevice device);
- void disconnect();
+ boolean disconnect(in BluetoothDevice device);
boolean isConnected(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 2b0c896..acd4ffa 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -234,6 +234,12 @@
out List<ComponentName> outActivities, String packageName);
/**
+ * Report the set of 'Home' activity candidates, plus (if any) which of them
+ * is the current "always use this one" setting.
+ */
+ ComponentName getHomeActivities(out List<ResolveInfo> outHomeCandidates);
+
+ /**
* As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
*/
void setComponentEnabledSetting(in ComponentName componentName,
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index d58b14c..416f489 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3027,6 +3027,13 @@
List<ComponentName> outActivities, String packageName);
/**
+ * Ask for the set of available 'home' activities and the current explicit
+ * default, if any.
+ * @hide
+ */
+ public abstract ComponentName getHomeActivities(List<ResolveInfo> outActivities);
+
+ /**
* Set the enabled setting for a package component (activity, receiver, service, provider).
* This setting will override any enabled state which may have been set by the component in its
* manifest.
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 75c0f7d..0c13b0f 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -89,6 +89,16 @@
public static final int TEMPLATE_VIDEO_SNAPSHOT = 4;
/**
+ * Create a request suitable for zero shutter lag still capture. This means
+ * means maximizing image quality without compromising preview frame rate.
+ * AE/AWB/AF should be on auto mode.
+ *
+ * @see #createCaptureRequest
+ * @hide
+ */
+ public static final int TEMPLATE_ZERO_SHUTTER_LAG = 5;
+
+ /**
* A basic template for direct application control of capture
* parameters. All automatic control is disabled (auto-exposure, auto-white
* balance, auto-focus), and post-processing parameters are set to preview
@@ -97,8 +107,9 @@
* application depending on the intended use case.
*
* @see #createCaptureRequest
+ * @hide
*/
- public static final int TEMPLATE_MANUAL = 5;
+ public static final int TEMPLATE_MANUAL = 6;
/**
* Get the ID of this camera device.
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index 76aea9f..648a4b3 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -38,7 +38,7 @@
private String mPacFileUrl;
public static final String LOCAL_EXCL_LIST = "";
- public static final int LOCAL_PORT = 8182;
+ public static final int LOCAL_PORT = -1;
public static final String LOCAL_HOST = "localhost";
public ProxyProperties(String host, int port, String exclList) {
@@ -54,6 +54,14 @@
mPacFileUrl = pacFileUrl;
}
+ // Only used in PacManager after Local Proxy is bound.
+ public ProxyProperties(String pacFileUrl, int localProxyPort) {
+ mHost = LOCAL_HOST;
+ mPort = localProxyPort;
+ setExclusionList(LOCAL_EXCL_LIST);
+ mPacFileUrl = pacFileUrl;
+ }
+
private ProxyProperties(String host, int port, String exclList, String[] parsedExclList) {
mHost = host;
mPort = port;
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 8f68fc1..eb91238 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -1018,6 +1018,28 @@
*/
public static native long getPss(int pid, long[] outUss);
+ /** @hide */
+ public static final int MEMINFO_TOTAL = 0;
+ /** @hide */
+ public static final int MEMINFO_FREE = 1;
+ /** @hide */
+ public static final int MEMINFO_BUFFERS = 2;
+ /** @hide */
+ public static final int MEMINFO_CACHED = 3;
+ /** @hide */
+ public static final int MEMINFO_SHMEM = 4;
+ /** @hide */
+ public static final int MEMINFO_SLAB = 5;
+ /** @hide */
+ public static final int MEMINFO_COUNT = 6;
+
+ /**
+ * Retrieves /proc/meminfo. outSizes is filled with fields
+ * as defined by MEMINFO_* offsets.
+ * @hide
+ */
+ public static native void getMemInfo(long[] outSizes);
+
/**
* Establish an object allocation limit in the current thread.
* This feature was never enabled in release builds. The
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index c6e8c3e..5b36bca 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -460,7 +460,13 @@
* top-level public directory, as this convention makes no sense elsewhere.
*/
public static String DIRECTORY_DCIM = "DCIM";
-
+
+ /**
+ * Standard directory in which to place documents that have been created by
+ * the user.
+ */
+ public static String DIRECTORY_DOCUMENTS = "Documents";
+
/**
* Get a top-level public external storage directory for placing files of
* a particular type. This is where the user will typically place and
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 37ce065..3f33e80 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -64,9 +64,9 @@
// content://com.example/root/
// content://com.example/root/sdcard/
// content://com.example/root/sdcard/recent/
+ // content://com.example/root/sdcard/search/?query=pony
// content://com.example/document/12/
// content://com.example/document/12/children/
- // content://com.example/document/12/search/?query=pony
private DocumentsContract() {
}
@@ -174,7 +174,6 @@
* @see #FLAG_SUPPORTS_THUMBNAIL
* @see #FLAG_DIR_PREFERS_GRID
* @see #FLAG_DIR_SUPPORTS_CREATE
- * @see #FLAG_DIR_SUPPORTS_SEARCH
*/
public static final String COLUMN_FLAGS = "flags";
@@ -241,16 +240,6 @@
public static final int FLAG_DIR_SUPPORTS_CREATE = 1 << 3;
/**
- * Flag indicating that a directory supports search. Only valid when
- * {@link #COLUMN_MIME_TYPE} is {@link #MIME_TYPE_DIR}.
- *
- * @see #COLUMN_FLAGS
- * @see DocumentsProvider#querySearchDocuments(String, String,
- * String[])
- */
- public static final int FLAG_DIR_SUPPORTS_SEARCH = 1 << 4;
-
- /**
* Flag indicating that a directory prefers its contents be shown in a
* larger format grid. Usually suitable when a directory contains mostly
* pictures. Only valid when {@link #COLUMN_MIME_TYPE} is
@@ -258,7 +247,7 @@
*
* @see #COLUMN_FLAGS
*/
- public static final int FLAG_DIR_PREFERS_GRID = 1 << 5;
+ public static final int FLAG_DIR_PREFERS_GRID = 1 << 4;
/**
* Flag indicating that a directory prefers its contents be sorted by
@@ -267,7 +256,19 @@
*
* @see #COLUMN_FLAGS
*/
- public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 1 << 6;
+ public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 1 << 5;
+
+ /**
+ * Flag indicating that document titles should be hidden when viewing
+ * this directory in a larger format grid. For example, a directory
+ * containing only images may want the image thumbnails to speak for
+ * themselves. Only valid when {@link #COLUMN_MIME_TYPE} is
+ * {@link #MIME_TYPE_DIR}.
+ *
+ * @see #COLUMN_FLAGS
+ * @see #FLAG_DIR_PREFERS_GRID
+ */
+ public static final int FLAG_DIR_HIDE_GRID_TITLES = 1 << 6;
}
/**
@@ -306,9 +307,12 @@
* <p>
* Type: INTEGER (int)
*
+ * @see #FLAG_ADVANCED
+ * @see #FLAG_EMPTY
* @see #FLAG_LOCAL_ONLY
* @see #FLAG_SUPPORTS_CREATE
- * @see #FLAG_ADVANCED
+ * @see #FLAG_SUPPORTS_RECENTS
+ * @see #FLAG_SUPPORTS_SEARCH
*/
public static final String COLUMN_FLAGS = "flags";
@@ -422,6 +426,27 @@
* @see DocumentsContract#buildRecentDocumentsUri(String, String)
*/
public static final int FLAG_SUPPORTS_RECENTS = 1 << 3;
+
+ /**
+ * Flag indicating that this root supports search.
+ *
+ * @see #COLUMN_FLAGS
+ * @see DocumentsProvider#querySearchDocuments(String, String,
+ * String[])
+ */
+ public static final int FLAG_SUPPORTS_SEARCH = 1 << 4;
+
+ /**
+ * Flag indicating that this root is currently empty. This may be used
+ * to hide the root when opening documents, but the root will still be
+ * shown when creating documents and {@link #FLAG_SUPPORTS_CREATE} is
+ * also set.
+ *
+ * @see #COLUMN_FLAGS
+ * @see DocumentsProvider#querySearchDocuments(String, String,
+ * String[])
+ */
+ public static final int FLAG_EMPTY = 1 << 5;
}
/**
@@ -493,9 +518,9 @@
}
/**
- * Build Uri representing the recently modified documents of a specific
- * root. When queried, a provider will return zero or more rows with columns
- * defined by {@link Document}.
+ * Build Uri representing the recently modified documents of a specific root
+ * in a document provider. When queried, a provider will return zero or more
+ * rows with columns defined by {@link Document}.
*
* @see DocumentsProvider#queryRecentDocuments(String, String[])
* @see #getRootId(Uri)
@@ -538,21 +563,17 @@
/**
* Build Uri representing a search for matching documents under a specific
- * directory in a document provider. When queried, a provider will return
- * zero or more rows with columns defined by {@link Document}.
+ * root in a document provider. When queried, a provider will return zero or
+ * more rows with columns defined by {@link Document}.
*
- * @param parentDocumentId the document to return children for, which must
- * be both a directory with MIME type of
- * {@link Document#MIME_TYPE_DIR} and have
- * {@link Document#FLAG_DIR_SUPPORTS_SEARCH} set.
* @see DocumentsProvider#querySearchDocuments(String, String, String[])
- * @see #getDocumentId(Uri)
+ * @see #getRootId(Uri)
* @see #getSearchDocumentsQuery(Uri)
*/
public static Uri buildSearchDocumentsUri(
- String authority, String parentDocumentId, String query) {
+ String authority, String rootId, String query) {
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority)
- .appendPath(PATH_DOCUMENT).appendPath(parentDocumentId).appendPath(PATH_SEARCH)
+ .appendPath(PATH_ROOT).appendPath(rootId).appendPath(PATH_SEARCH)
.appendQueryParameter(PARAM_QUERY, query).build();
}
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index d801827..bc4e28b 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -75,9 +75,9 @@
private static final int MATCH_ROOTS = 1;
private static final int MATCH_ROOT = 2;
private static final int MATCH_RECENT = 3;
- private static final int MATCH_DOCUMENT = 4;
- private static final int MATCH_CHILDREN = 5;
- private static final int MATCH_SEARCH = 6;
+ private static final int MATCH_SEARCH = 4;
+ private static final int MATCH_DOCUMENT = 5;
+ private static final int MATCH_CHILDREN = 6;
private String mAuthority;
@@ -94,9 +94,9 @@
mMatcher.addURI(mAuthority, "root", MATCH_ROOTS);
mMatcher.addURI(mAuthority, "root/*", MATCH_ROOT);
mMatcher.addURI(mAuthority, "root/*/recent", MATCH_RECENT);
+ mMatcher.addURI(mAuthority, "root/*/search", MATCH_SEARCH);
mMatcher.addURI(mAuthority, "document/*", MATCH_DOCUMENT);
mMatcher.addURI(mAuthority, "document/*/children", MATCH_CHILDREN);
- mMatcher.addURI(mAuthority, "document/*/search", MATCH_SEARCH);
// Sanity check our setup
if (!info.exported) {
@@ -176,13 +176,12 @@
}
/**
- * Return documents that that match the given query, starting the search at
- * the given directory.
+ * Return documents that that match the given query.
*
- * @param parentDocumentId the directory to start search at.
+ * @param rootId the root to search under.
*/
@SuppressWarnings("unused")
- public Cursor querySearchDocuments(String parentDocumentId, String query, String[] projection)
+ public Cursor querySearchDocuments(String rootId, String query, String[] projection)
throws FileNotFoundException {
throw new UnsupportedOperationException("Search not supported");
}
@@ -267,6 +266,9 @@
return queryRoots(projection);
case MATCH_RECENT:
return queryRecentDocuments(getRootId(uri), projection);
+ case MATCH_SEARCH:
+ return querySearchDocuments(
+ getRootId(uri), getSearchDocumentsQuery(uri), projection);
case MATCH_DOCUMENT:
return queryDocument(getDocumentId(uri), projection);
case MATCH_CHILDREN:
@@ -276,9 +278,6 @@
} else {
return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
}
- case MATCH_SEARCH:
- return querySearchDocuments(
- getDocumentId(uri), getSearchDocumentsQuery(uri), projection);
default:
throw new UnsupportedOperationException("Unsupported Uri " + uri);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 025926e..af905b4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5642,6 +5642,9 @@
/** {@hide} */
public static final String
BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX = "bluetooth_input_device_priority_";
+ /** {@hide} */
+ public static final String
+ BLUETOOTH_MAP_PRIORITY_PREFIX = "bluetooth_map_priority_";
/**
* Get the key that retrieves a bluetooth headset's priority.
@@ -5668,6 +5671,13 @@
}
/**
+ * Get the key that retrieves a bluetooth map priority.
+ * @hide
+ */
+ public static final String getBluetoothMapPriorityKey(String address) {
+ return BLUETOOTH_MAP_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
+ }
+ /**
* Scaling factor for normal window animations. Setting to 0 will
* disable window animations.
*/
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 30ca73e..58cd60d 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -49,12 +49,12 @@
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
- PROC_SPACE_TERM|PROC_OUT_LONG, // 9: minor faults
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 10: minor faults
PROC_SPACE_TERM,
- PROC_SPACE_TERM|PROC_OUT_LONG, // 11: major faults
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 12: major faults
PROC_SPACE_TERM,
- PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime
- PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 14: utime
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 15: stime
};
static final int PROCESS_STAT_MINOR_FAULTS = 0;
@@ -69,7 +69,7 @@
private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
PROC_SPACE_TERM,
- PROC_SPACE_TERM|PROC_PARENS|PROC_OUT_STRING, // 1: name
+ PROC_SPACE_TERM|PROC_PARENS|PROC_OUT_STRING, // 2: name
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
@@ -77,19 +77,20 @@
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
- PROC_SPACE_TERM|PROC_OUT_LONG, // 9: minor faults
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 10: minor faults
PROC_SPACE_TERM,
- PROC_SPACE_TERM|PROC_OUT_LONG, // 11: major faults
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 12: major faults
PROC_SPACE_TERM,
- PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime
- PROC_SPACE_TERM|PROC_OUT_LONG, // 14: stime
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 14: utime
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 15: stime
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
- PROC_SPACE_TERM|PROC_OUT_LONG, // 21: vsize
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 23: vsize
};
static final int PROCESS_FULL_STAT_MINOR_FAULTS = 1;
@@ -190,6 +191,10 @@
public String name;
public int nameWidth;
+ // vsize capture when process first detected; can be used to
+ // filter out kernel processes.
+ public long vsize;
+
public long base_uptime;
public long rel_uptime;
@@ -444,6 +449,7 @@
// are actually kernel threads... do we want to? Some
// of them do use CPU, but there can be a *lot* that are
// not doing anything.
+ st.vsize = procStats[PROCESS_FULL_STAT_VSIZE];
if (true || procStats[PROCESS_FULL_STAT_VSIZE] != 0) {
st.interesting = true;
st.baseName = procStatsString[0];
diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java
index 850e1f0..ad65433 100644
--- a/core/java/com/android/internal/util/MemInfoReader.java
+++ b/core/java/com/android/internal/util/MemInfoReader.java
@@ -18,6 +18,7 @@
import java.io.FileInputStream;
+import android.os.Debug;
import android.os.StrictMode;
public class MemInfoReader {
@@ -63,34 +64,11 @@
// /proc/ and /sys/ files perhaps?
StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
try {
- mTotalSize = 0;
- mFreeSize = 0;
- mCachedSize = 0;
- FileInputStream is = new FileInputStream("/proc/meminfo");
- int len = is.read(mBuffer);
- is.close();
- final int BUFLEN = mBuffer.length;
- int count = 0;
- for (int i=0; i<len && count < 3; i++) {
- if (matchText(mBuffer, i, "MemTotal")) {
- i += 8;
- mTotalSize = extractMemValue(mBuffer, i);
- count++;
- } else if (matchText(mBuffer, i, "MemFree")) {
- i += 7;
- mFreeSize = extractMemValue(mBuffer, i);
- count++;
- } else if (matchText(mBuffer, i, "Cached")) {
- i += 6;
- mCachedSize = extractMemValue(mBuffer, i);
- count++;
- }
- while (i < BUFLEN && mBuffer[i] != '\n') {
- i++;
- }
- }
- } catch (java.io.FileNotFoundException e) {
- } catch (java.io.IOException e) {
+ long[] infos = new long[Debug.MEMINFO_COUNT];
+ Debug.getMemInfo(infos);
+ mTotalSize = infos[Debug.MEMINFO_TOTAL] * 1024;
+ mFreeSize = infos[Debug.MEMINFO_FREE] * 1024;
+ mCachedSize = infos[Debug.MEMINFO_CACHED] * 1024;
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 1779c9f..60540f4 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -516,6 +516,87 @@
return android_os_Debug_getPssPid(env, clazz, getpid(), NULL);
}
+static void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray out)
+{
+ char buffer[1024];
+ int numFound = 0;
+
+ if (out == NULL) {
+ jniThrowNullPointerException(env, "out == null");
+ return;
+ }
+
+ int fd = open("/proc/meminfo", O_RDONLY);
+
+ if (fd < 0) {
+ printf("Unable to open /proc/meminfo: %s\n", strerror(errno));
+ return;
+ }
+
+ const int len = read(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ if (len < 0) {
+ printf("Empty /proc/meminfo");
+ return;
+ }
+ buffer[len] = 0;
+
+ static const char* const tags[] = {
+ "MemTotal:",
+ "MemFree:",
+ "Buffers:",
+ "Cached:",
+ "Shmem:",
+ "Slab:",
+ NULL
+ };
+ static const int tagsLen[] = {
+ 9,
+ 8,
+ 8,
+ 7,
+ 6,
+ 5,
+ 0
+ };
+ long mem[] = { 0, 0, 0, 0, 0, 0 };
+
+ char* p = buffer;
+ while (*p && numFound < 6) {
+ int i = 0;
+ while (tags[i]) {
+ if (strncmp(p, tags[i], tagsLen[i]) == 0) {
+ p += tagsLen[i];
+ while (*p == ' ') p++;
+ char* num = p;
+ while (*p >= '0' && *p <= '9') p++;
+ if (*p != 0) {
+ *p = 0;
+ p++;
+ }
+ mem[i] = atoll(num);
+ numFound++;
+ break;
+ }
+ i++;
+ }
+ while (*p && *p != '\n') {
+ p++;
+ }
+ if (*p) p++;
+ }
+
+ int maxNum = env->GetArrayLength(out);
+ jlong* outArray = env->GetLongArrayElements(out, 0);
+ if (outArray != NULL) {
+ for (int i=0; i<maxNum && tags[i]; i++) {
+ outArray[i] = mem[i];
+ }
+ }
+ env->ReleaseLongArrayElements(out, outArray, 0);
+}
+
static jint read_binder_stat(const char* stat)
{
FILE* fp = fopen(BINDER_STATS, "r");
@@ -790,6 +871,8 @@
(void*) android_os_Debug_getPss },
{ "getPss", "(I[J)J",
(void*) android_os_Debug_getPssPid },
+ { "getMemInfo", "([J)V",
+ (void*) android_os_Debug_getMemInfo },
{ "dumpNativeHeap", "(Ljava/io/FileDescriptor;)V",
(void*) android_os_Debug_dumpNativeHeap },
{ "getBinderSentTransactions", "()I",
diff --git a/core/res/res/values-mcc510-mnc21/config.xml b/core/res/res/values-mcc510-mnc21/config.xml
new file mode 100644
index 0000000..1fd9dfa
--- /dev/null
+++ b/core/res/res/values-mcc510-mnc21/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>51001</item>
+ </string-array>
+</resources>
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 0d9a386..2846e61 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -138,8 +138,7 @@
DroidSansHebrew-Regular.ttf \
DroidSansHebrew-Bold.ttf \
DroidSansArmenian.ttf \
- DroidSansGeorgian.ttf \
- AndroidEmoji.ttf
+ DroidSansGeorgian.ttf
endif # !MINIMAL_FONT
diff --git a/data/fonts/AndroidEmoji.ttf b/data/fonts/AndroidEmoji.ttf
deleted file mode 100644
index 569cbab..0000000
--- a/data/fonts/AndroidEmoji.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 1198aba..69db6aa 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -186,7 +186,7 @@
</family>
<family>
<fileset>
- <file>AndroidEmoji.ttf</file>
+ <file>NotoColorEmoji.ttf</file>
</fileset>
</family>
<family>
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 05cca13e..a677c4f 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -43,7 +43,6 @@
DroidSansMono.ttf \
DroidSansArmenian.ttf \
DroidSansGeorgian.ttf \
- AndroidEmoji.ttf \
Clockopia.ttf \
AndroidClock.ttf \
AndroidClock_Highlight.ttf \
diff --git a/docs/html/guide/topics/manifest/uses-sdk-element.jd b/docs/html/guide/topics/manifest/uses-sdk-element.jd
index 18e479f..07b08f6 100644
--- a/docs/html/guide/topics/manifest/uses-sdk-element.jd
+++ b/docs/html/guide/topics/manifest/uses-sdk-element.jd
@@ -1,4 +1,4 @@
-fpage.title=<uses-sdk>
+page.title=<uses-sdk>
page.tags="api levels","sdk version","minsdkversion","targetsdkversion","maxsdkversion"
@jd:body
diff --git a/obex/javax/obex/ClientOperation.java b/obex/javax/obex/ClientOperation.java
index 294b502..0c65283 100644
--- a/obex/javax/obex/ClientOperation.java
+++ b/obex/javax/obex/ClientOperation.java
@@ -121,6 +121,13 @@
(header).mAuthResp.length);
}
+
+ if ((header).mConnectionID != null) {
+ mRequestHeader.mConnectionID = new byte[4];
+ System.arraycopy((header).mConnectionID, 0, mRequestHeader.mConnectionID, 0,
+ 4);
+
+ }
}
/**
@@ -420,7 +427,7 @@
//split the headerArray
end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketSize
- ObexHelper.BASE_PACKET_LENGTH);
- // can not split
+ // can not split
if (end == -1) {
mOperationDone = true;
abort();
@@ -521,7 +528,7 @@
return false;
}
- // send all of the output data in 0x48,
+ // send all of the output data in 0x48,
// send 0x49 with empty body
if ((mPrivateOutput != null) && (mPrivateOutput.size() > 0))
returnValue = true;
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
index a4b9759..f1b9a0d 100644
--- a/obex/javax/obex/ServerSession.java
+++ b/obex/javax/obex/ServerSession.java
@@ -256,6 +256,10 @@
public void sendResponse(int code, byte[] header) throws IOException {
int totalLength = 3;
byte[] data = null;
+ OutputStream op = mOutput;
+ if (op == null) {
+ return;
+ }
if (header != null) {
totalLength += header.length;
@@ -270,8 +274,8 @@
data[1] = (byte)0x00;
data[2] = (byte)totalLength;
}
- mOutput.write(data);
- mOutput.flush();
+ op.write(data);
+ op.flush();
}
/**
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index 3cfae64..b745bb9 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -30,6 +30,7 @@
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
+ android:layout_marginBottom="6dp"
android:background="#fff">
<FrameLayout
@@ -63,10 +64,10 @@
</FrameLayout>
<LinearLayout
+ android:id="@+id/line1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:paddingTop="6dp"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
@@ -121,6 +122,20 @@
android:textAlignment="viewStart"
style="@style/TextAppearance.Small" />
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <ImageView
+ android:id="@android:id/icon2"
+ android:layout_width="@dimen/root_icon_size"
+ android:layout_height="@dimen/root_icon_size"
+ android:layout_marginStart="8dip"
+ android:scaleType="centerInside"
+ android:contentDescription="@null"
+ android:visibility="gone" />
+
</LinearLayout>
</LinearLayout>
diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml
index 6c37a4e..d995376 100644
--- a/packages/DocumentsUI/res/menu/activity.xml
+++ b/packages/DocumentsUI/res/menu/activity.xml
@@ -19,7 +19,7 @@
android:id="@+id/menu_create_dir"
android:title="@string/menu_create_dir"
android:icon="@drawable/ic_menu_new_folder"
- android:showAsAction="ifRoom" />
+ android:showAsAction="always" />
<item
android:id="@+id/menu_search"
android:title="@string/menu_search"
@@ -48,12 +48,12 @@
android:id="@+id/menu_grid"
android:title="@string/menu_grid"
android:icon="@drawable/ic_menu_view_grid"
- android:showAsAction="ifRoom" />
+ android:showAsAction="never" />
<item
android:id="@+id/menu_list"
android:title="@string/menu_list"
android:icon="@drawable/ic_menu_view_list"
- android:showAsAction="ifRoom" />
+ android:showAsAction="never" />
<item
android:id="@+id/menu_settings"
android:title="@string/menu_settings"
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index b2981db..198927c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -102,6 +102,8 @@
private int mLastSortOrder = SORT_ORDER_UNKNOWN;
private boolean mLastShowSize = false;
+ private boolean mHideGridTitles = false;
+
private Point mThumbSize;
private DocumentsAdapter mAdapter;
@@ -112,11 +114,6 @@
private static final String EXTRA_DOC = "doc";
private static final String EXTRA_QUERY = "query";
- /**
- * MIME types that should always show thumbnails in list mode.
- */
- private static final String[] LIST_THUMBNAIL_MIMES = new String[] { "image/*", "video/*" };
-
private static AtomicInteger sLoaderId = new AtomicInteger(4000);
private final int mLoaderId = sLoaderId.incrementAndGet();
@@ -125,9 +122,8 @@
show(fm, TYPE_NORMAL, root, doc, null);
}
- public static void showSearch(
- FragmentManager fm, RootInfo root, DocumentInfo doc, String query) {
- show(fm, TYPE_SEARCH, root, doc, query);
+ public static void showSearch(FragmentManager fm, RootInfo root, String query) {
+ show(fm, TYPE_SEARCH, root, null, query);
}
public static void showRecentsOpen(FragmentManager fm) {
@@ -183,14 +179,23 @@
final Context context = getActivity();
final State state = getDisplayState(DirectoryFragment.this);
+ final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
+ final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
+
mAdapter = new DocumentsAdapter();
mType = getArguments().getInt(EXTRA_TYPE);
+ if (mType == TYPE_RECENT_OPEN) {
+ // Hide titles when showing recents for picking images/videos
+ mHideGridTitles = MimePredicate.mimeMatches(
+ MimePredicate.VISUAL_MIMES, state.acceptMimes);
+ } else {
+ mHideGridTitles = (doc != null) && doc.isGridTitlesHidden();
+ }
+
mCallbacks = new LoaderCallbacks<DirectoryResult>() {
@Override
public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
- final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
- final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
final String query = getArguments().getString(EXTRA_QUERY);
Uri contentsUri;
@@ -205,7 +210,7 @@
context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_SEARCH:
contentsUri = DocumentsContract.buildSearchDocumentsUri(
- doc.authority, doc.documentId, query);
+ root.authority, root.rootId, query);
if (state.action == ACTION_MANAGE) {
contentsUri = DocumentsContract.setManageMode(contentsUri);
}
@@ -274,7 +279,7 @@
final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
- if (root != null) {
+ if (root != null && doc != null) {
final Uri stateUri = RecentsProvider.buildState(
root.authority, root.rootId, doc.documentId);
final ContentValues values = new ContentValues();
@@ -644,6 +649,8 @@
final Context context = parent.getContext();
final State state = getDisplayState(DirectoryFragment.this);
+ final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
+
final RootsCache roots = DocumentsApplication.getRootsCache(context);
final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
context, mThumbSize);
@@ -672,12 +679,15 @@
final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY);
final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE);
+ final View line1 = convertView.findViewById(R.id.line1);
+ final View line2 = convertView.findViewById(R.id.line2);
+
final View icon = convertView.findViewById(android.R.id.icon);
final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime);
final ImageView iconThumb = (ImageView) convertView.findViewById(R.id.icon_thumb);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
- final View line2 = convertView.findViewById(R.id.line2);
final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1);
+ final ImageView icon2 = (ImageView) convertView.findViewById(android.R.id.icon2);
final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
final TextView date = (TextView) convertView.findViewById(R.id.date);
final TextView size = (TextView) convertView.findViewById(R.id.size);
@@ -693,10 +703,11 @@
final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
final boolean allowThumbnail = (state.derivedMode == MODE_GRID)
- || MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType);
+ || MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, docMimeType);
+ final boolean showThumbnail = supportsThumbnail && allowThumbnail;
boolean cacheHit = false;
- if (supportsThumbnail && allowThumbnail) {
+ if (showThumbnail) {
final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId);
final Bitmap cachedResult = thumbs.get(uri);
if (cachedResult != null) {
@@ -727,15 +738,19 @@
}
}
- title.setText(docDisplayName);
-
+ boolean hasLine1 = false;
boolean hasLine2 = false;
+ final boolean hideTitle = (state.derivedMode == MODE_GRID) && mHideGridTitles;
+ if (!hideTitle) {
+ title.setText(docDisplayName);
+ hasLine1 = true;
+ }
+
+ Drawable iconDrawable = null;
if (mType == TYPE_RECENT_OPEN) {
final RootInfo root = roots.getRoot(docAuthority, docRootId);
- final Drawable iconDrawable = root.loadIcon(context);
- icon1.setVisibility(View.VISIBLE);
- icon1.setImageDrawable(iconDrawable);
+ iconDrawable = root.loadIcon(context);
if (summary != null) {
final boolean alwaysShowSummary = getResources()
@@ -757,7 +772,13 @@
}
}
} else {
- icon1.setVisibility(View.GONE);
+ // Directories showing thumbnails in grid mode get a little icon
+ // hint to remind user they're a directory.
+ if (Document.MIME_TYPE_DIR.equals(docMimeType) && state.derivedMode == MODE_GRID
+ && showThumbnail) {
+ iconDrawable = context.getResources().getDrawable(R.drawable.ic_root_folder);
+ }
+
if (summary != null) {
if (docSummary != null) {
summary.setText(docSummary);
@@ -769,6 +790,19 @@
}
}
+ if (icon1 != null) icon1.setVisibility(View.GONE);
+ if (icon2 != null) icon2.setVisibility(View.GONE);
+
+ if (iconDrawable != null) {
+ if (hasLine1) {
+ icon1.setVisibility(View.VISIBLE);
+ icon1.setImageDrawable(iconDrawable);
+ } else {
+ icon2.setVisibility(View.VISIBLE);
+ icon2.setImageDrawable(iconDrawable);
+ }
+ }
+
if (docLastModified == -1) {
date.setText(null);
} else {
@@ -788,6 +822,9 @@
size.setVisibility(View.GONE);
}
+ if (line1 != null) {
+ line1.setVisibility(hasLine1 ? View.VISIBLE : View.GONE);
+ }
if (line2 != null) {
line2.setVisibility(hasLine2 ? View.VISIBLE : View.GONE);
}
@@ -797,11 +834,13 @@
if (enabled) {
setEnabledRecursive(convertView, true);
icon.setAlpha(1f);
- icon1.setAlpha(1f);
+ if (icon1 != null) icon1.setAlpha(1f);
+ if (icon2 != null) icon2.setAlpha(1f);
} else {
setEnabledRecursive(convertView, false);
icon.setAlpha(0.5f);
- icon1.setAlpha(0.5f);
+ if (icon1 != null) icon1.setAlpha(0.5f);
+ if (icon2 != null) icon2.setAlpha(0.5f);
}
return convertView;
@@ -944,6 +983,7 @@
}
private void setEnabledRecursive(View v, boolean enabled) {
+ if (v == null) return;
if (v.isEnabled() == enabled) return;
v.setEnabled(enabled);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 334e262..8627ecf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -32,6 +32,7 @@
import android.net.Uri;
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
+import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.util.Log;
@@ -42,6 +43,8 @@
import libcore.io.IoUtils;
+import java.io.FileNotFoundException;
+
class DirectoryResult implements AutoCloseable {
ContentProviderClient client;
Cursor cursor;
@@ -64,7 +67,7 @@
private final int mType;
private final RootInfo mRoot;
- private final DocumentInfo mDoc;
+ private DocumentInfo mDoc;
private final Uri mUri;
private final int mUserSortOrder;
@@ -97,6 +100,19 @@
int userMode = State.MODE_UNKNOWN;
+ // Use default document when searching
+ if (mType == DirectoryFragment.TYPE_SEARCH) {
+ final Uri docUri = DocumentsContract.buildDocumentUri(
+ mRoot.authority, mRoot.documentId);
+ try {
+ mDoc = DocumentInfo.fromUri(resolver, docUri);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Failed to query", e);
+ result.exception = e;
+ return result;
+ }
+ }
+
// Pick up any custom modes requested by user
Cursor cursor = null;
try {
@@ -157,7 +173,7 @@
result.cursor = cursor;
} catch (Exception e) {
- Log.d(TAG, "Failed to query", e);
+ Log.w(TAG, "Failed to query", e);
result.exception = e;
ContentProviderClient.closeQuietly(result.client);
} finally {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index eb51fb5..f6cb481 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -45,6 +45,7 @@
import android.os.Bundle;
import android.os.Parcel;
import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Root;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
@@ -243,6 +244,7 @@
} else {
// Restore last stack for calling package
// TODO: move into async loader
+ boolean restoredStack = false;
final String packageName = getCallingPackage();
final Cursor cursor = getContentResolver()
.query(RecentsProvider.buildResume(packageName), null, null, null, null);
@@ -251,6 +253,7 @@
final byte[] rawStack = cursor.getBlob(
cursor.getColumnIndex(ResumeColumns.STACK));
DurableUtils.readFromArray(rawStack, mState.stack);
+ restoredStack = true;
}
} catch (IOException e) {
Log.w(TAG, "Failed to resume", e);
@@ -263,10 +266,13 @@
final List<RootInfo> matchingRoots = mRoots.getMatchingRoots(mState);
if (!matchingRoots.contains(root)) {
mState.stack.reset();
+ restoredStack = false;
}
- // Only open drawer when showing recents
- if (mState.stack.isRecents()) {
+ // Only open drawer when not restoring stack, and when not showing
+ // visual content.
+ if (!restoredStack
+ && !MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) {
setRootsDrawerOpen(true);
}
}
@@ -442,6 +448,8 @@
super.onPrepareOptionsMenu(menu);
final FragmentManager fm = getFragmentManager();
+
+ final RootInfo root = getCurrentRoot();
final DocumentInfo cwd = getCurrentDirectory();
final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
@@ -503,7 +511,9 @@
SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
} else {
createDir.setVisible(false);
- searchVisible = cwd != null && cwd.isSearchSupported();
+
+ searchVisible = root != null
+ && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0);
}
// TODO: close any search in-progress when hiding
@@ -722,7 +732,7 @@
} else {
if (mState.currentSearch != null) {
// Ongoing search
- DirectoryFragment.showSearch(fm, root, cwd, mState.currentSearch);
+ DirectoryFragment.showSearch(fm, root, mState.currentSearch);
} else {
// Normal boring directory
DirectoryFragment.showNormal(fm, root, cwd);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
index b55ce82..2d96876 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
@@ -22,6 +22,12 @@
public class MimePredicate implements Predicate<DocumentInfo> {
private final String[] mFilters;
+ /**
+ * MIME types that are visual in nature. For example, they should always be
+ * shown as thumbnails in list mode.
+ */
+ public static final String[] VISUAL_MIMES = new String[] { "image/*", "video/*" };
+
public MimePredicate(String[] filters) {
mFilters = filters;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index a7173b6..1912010 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -27,6 +27,7 @@
import android.database.MergeCursor;
import android.net.Uri;
import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.util.Log;
@@ -176,7 +177,7 @@
try {
final Cursor cursor = task.get();
final FilteringCursorWrapper filtered = new FilteringCursorWrapper(
- cursor, mAcceptMimes) {
+ cursor, mAcceptMimes, new String[] { Document.MIME_TYPE_DIR }) {
@Override
public void close() {
// Ignored, since we manage cursor lifecycle internally
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index b48674cf..9b54948 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -137,12 +137,14 @@
@GuardedBy("ActivityThread")
public boolean isIconUnique(RootInfo root) {
+ final int rootIcon = root.derivedIcon != 0 ? root.derivedIcon : root.icon;
for (RootInfo test : mRoots) {
if (Objects.equal(test.authority, root.authority)) {
if (Objects.equal(test.rootId, root.rootId)) {
continue;
}
- if (test.icon == root.icon) {
+ final int testIcon = test.derivedIcon != 0 ? test.derivedIcon : test.icon;
+ if (testIcon == rootIcon) {
return false;
}
}
@@ -176,6 +178,7 @@
final boolean supportsCreate = (root.flags & Root.FLAG_SUPPORTS_CREATE) != 0;
final boolean advanced = (root.flags & Root.FLAG_ADVANCED) != 0;
final boolean localOnly = (root.flags & Root.FLAG_LOCAL_ONLY) != 0;
+ final boolean empty = (root.flags & Root.FLAG_EMPTY) != 0;
// Exclude read-only devices when creating
if (state.action == State.ACTION_CREATE && !supportsCreate) continue;
@@ -183,6 +186,8 @@
if (!state.showAdvanced && advanced) continue;
// Exclude non-local devices when local only
if (state.localOnly && !localOnly) continue;
+ // Only show empty roots when creating
+ if (state.action != State.ACTION_CREATE && empty) continue;
// Only include roots that serve requested content
final boolean overlap =
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 54dcf1c..908729c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -35,6 +35,7 @@
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
+import android.widget.Space;
import android.widget.TextView;
import com.android.documentsui.DocumentsActivity.State;
@@ -136,11 +137,8 @@
};
private static class RootsAdapter extends ArrayAdapter<RootInfo> implements SectionAdapter {
- private int mHeaderId;
-
- public RootsAdapter(Context context, int headerId) {
+ public RootsAdapter(Context context) {
super(context, 0);
- mHeaderId = headerId;
}
@Override
@@ -177,13 +175,8 @@
@Override
public View getHeaderView(View convertView, ViewGroup parent) {
if (convertView == null) {
- convertView = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.item_root_header, parent, false);
+ convertView = new Space(parent.getContext());
}
-
- final TextView title = (TextView) convertView.findViewById(android.R.id.title);
- title.setText(mHeaderId);
-
return convertView;
}
}
@@ -237,9 +230,9 @@
private final AppsAdapter mApps;
public SectionedRootsAdapter(Context context, List<RootInfo> roots, Intent includeApps) {
- mServices = new RootsAdapter(context, R.string.root_type_service);
- mShortcuts = new RootsAdapter(context, R.string.root_type_shortcut);
- mDevices = new RootsAdapter(context, R.string.root_type_device);
+ mServices = new RootsAdapter(context);
+ mShortcuts = new RootsAdapter(context);
+ mDevices = new RootsAdapter(context);
mApps = new AppsAdapter(context);
for (RootInfo root : roots) {
@@ -274,15 +267,15 @@
mShortcuts.sort(comp);
mDevices.sort(comp);
- if (mServices.getCount() > 0) {
- addSection(mServices);
- }
if (mShortcuts.getCount() > 0) {
addSection(mShortcuts);
}
if (mDevices.getCount() > 0) {
addSection(mDevices);
}
+ if (mServices.getCount() > 0) {
+ addSection(mServices);
+ }
if (mApps.getCount() > 0) {
addSection(mApps);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index c69103e..681cc9b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -188,10 +188,6 @@
return (flags & Document.FLAG_DIR_SUPPORTS_CREATE) != 0;
}
- public boolean isSearchSupported() {
- return (flags & Document.FLAG_DIR_SUPPORTS_SEARCH) != 0;
- }
-
public boolean isThumbnailSupported() {
return (flags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
}
@@ -208,6 +204,10 @@
return (flags & Document.FLAG_SUPPORTS_DELETE) != 0;
}
+ public boolean isGridTitlesHidden() {
+ return (flags & Document.FLAG_DIR_HIDE_GRID_TITLES) != 0;
+ }
+
public static String getCursorString(Cursor cursor, String columnName) {
final int index = cursor.getColumnIndex(columnName);
return (index != -1) ? cursor.getString(index) : null;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index b5a198c..1afc80a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -161,15 +161,21 @@
// TODO: remove these special case icons
if ("com.android.externalstorage.documents".equals(authority)) {
- derivedIcon = R.drawable.ic_root_sdcard;
+ if ("documents".equals(rootId)) {
+ derivedIcon = R.drawable.ic_doc_text;
+ } else {
+ derivedIcon = R.drawable.ic_root_sdcard;
+ }
}
if ("com.android.providers.downloads.documents".equals(authority)) {
derivedIcon = R.drawable.ic_root_download;
}
if ("com.android.providers.media.documents".equals(authority)) {
- if ("image".equals(rootId)) {
+ if ("images_root".equals(rootId)) {
derivedIcon = R.drawable.ic_doc_image;
- } else if ("audio".equals(rootId)) {
+ } else if ("videos_root".equals(rootId)) {
+ derivedIcon = R.drawable.ic_doc_video;
+ } else if ("audio_root".equals(rootId)) {
derivedIcon = R.drawable.ic_doc_audio;
}
}
diff --git a/packages/ExternalStorageProvider/res/values/strings.xml b/packages/ExternalStorageProvider/res/values/strings.xml
index 0eaf500a..f1c1ade 100644
--- a/packages/ExternalStorageProvider/res/values/strings.xml
+++ b/packages/ExternalStorageProvider/res/values/strings.xml
@@ -15,6 +15,11 @@
-->
<resources>
+ <!-- Title of the external storage application [CHAR LIMIT=32] -->
<string name="app_label">External Storage</string>
+
+ <!-- Title for documents backend that offers internal storage. [CHAR LIMIT=24] -->
<string name="root_internal_storage">Internal storage</string>
+ <!-- Title for documents backend that offers documents. [CHAR LIMIT=24] -->
+ <string name="root_documents">Documents</string>
</resources>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index ada3ad7..3e2cd15 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -62,7 +62,6 @@
public String rootId;
public int rootType;
public int flags;
- public int icon;
public String title;
public String docId;
}
@@ -85,9 +84,10 @@
mIdToPath.put(rootId, path);
final RootInfo root = new RootInfo();
- root.rootId = "primary";
+ root.rootId = rootId;
root.rootType = Root.ROOT_TYPE_DEVICE;
- root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED;
+ root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
+ | Root.FLAG_SUPPORTS_SEARCH;
root.title = getContext().getString(R.string.root_internal_storage);
root.docId = getDocIdForFile(path);
mRoots.add(root);
@@ -96,6 +96,25 @@
throw new IllegalStateException(e);
}
+ try {
+ final String rootId = "documents";
+ final File path = Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DOCUMENTS);
+ mIdToPath.put(rootId, path);
+
+ final RootInfo root = new RootInfo();
+ root.rootId = rootId;
+ root.rootType = Root.ROOT_TYPE_SHORTCUT;
+ root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY
+ | Root.FLAG_SUPPORTS_SEARCH;
+ root.title = getContext().getString(R.string.root_documents);
+ root.docId = getDocIdForFile(path);
+ mRoots.add(root);
+ mIdToRoot.put(rootId, root);
+ } catch (FileNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
+
return true;
}
@@ -146,6 +165,9 @@
if (target == null) {
throw new FileNotFoundException("No root for " + tag);
}
+ if (!target.exists()) {
+ target.mkdirs();
+ }
target = new File(target, path);
if (!target.exists()) {
throw new FileNotFoundException("Missing file for " + docId + " at " + target);
@@ -163,9 +185,6 @@
int flags = 0;
- if (file.isDirectory()) {
- flags |= Document.FLAG_DIR_SUPPORTS_SEARCH;
- }
if (file.isDirectory() && file.canWrite()) {
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
}
@@ -200,7 +219,6 @@
row.add(Root.COLUMN_ROOT_ID, root.rootId);
row.add(Root.COLUMN_ROOT_TYPE, root.rootType);
row.add(Root.COLUMN_FLAGS, root.flags);
- row.add(Root.COLUMN_ICON, root.icon);
row.add(Root.COLUMN_TITLE, root.title);
row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
row.add(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
@@ -260,10 +278,10 @@
}
@Override
- public Cursor querySearchDocuments(String parentDocumentId, String query, String[] projection)
+ public Cursor querySearchDocuments(String rootId, String query, String[] projection)
throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
- final File parent = getFileForDocId(parentDocumentId);
+ final File parent = mIdToPath.get(rootId);
final LinkedList<File> pending = new LinkedList<File>();
pending.add(parent);
diff --git a/packages/SystemUI/res/values-az-rAZ-land/strings.xml b/packages/SystemUI/res/values-az-rAZ-land/strings.xml
new file mode 100644
index 0000000..8eb6978
--- /dev/null
+++ b/packages/SystemUI/res/values-az-rAZ-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Hazırda ekran landşaft orientasiyasında kilidlənib."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rIN-land/strings.xml b/packages/SystemUI/res/values-en-rIN-land/strings.xml
new file mode 100644
index 0000000..ba773b8
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rIN-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Screen is now locked in landscape orientation."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-et-rEE-land/strings.xml b/packages/SystemUI/res/values-et-rEE-land/strings.xml
new file mode 100644
index 0000000..77b0ce1
--- /dev/null
+++ b/packages/SystemUI/res/values-et-rEE-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Ekraan on nüüd lukustatud horisontaalasendisse."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA-land/strings.xml b/packages/SystemUI/res/values-fr-rCA-land/strings.xml
new file mode 100644
index 0000000..4775fc6
--- /dev/null
+++ b/packages/SystemUI/res/values-fr-rCA-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"L\'écran est désormais verrouillé au format paysage."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f9ede31..4c3c87f 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -22,7 +22,7 @@
<string name="app_label" msgid="7164937344850004466">"सिस्टम UI"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"साफ़ करें"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"सूची से निकालें"</string>
- <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"एप्लिकेशन जानकारी"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"एप्स जानकारी"</string>
<string name="status_bar_no_recent_apps" msgid="6576392951053994640">"कोई हाल ही के एप्स नहीं"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"हाल ही के एप्स खारिज करें"</string>
<plurals name="status_bar_accessibility_recent_apps">
@@ -40,7 +40,7 @@
<string name="status_bar_settings_settings_button" msgid="3023889916699270224">"सेटिंग"</string>
<string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
<string name="status_bar_settings_airplane" msgid="4879879698500955300">"हवाई जहाज मोड"</string>
- <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्क्रीन स्वत: घुमाएं"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्क्रीन अपनेआप घुमाएं"</string>
<string name="status_bar_settings_mute_label" msgid="554682549917429396">"म्यूट करें"</string>
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"स्वत:"</string>
<string name="status_bar_settings_notifications" msgid="397146176280905137">"सूचनाएं"</string>
@@ -75,7 +75,7 @@
<string name="accessibility_back" msgid="567011538994429120">"वापस जाएं"</string>
<string name="accessibility_home" msgid="8217216074895377641">"होम"</string>
<string name="accessibility_menu" msgid="316839303324695949">"मेनू"</string>
- <string name="accessibility_recent" msgid="8571350598987952883">"हाल ही के एप्लिकेशन"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"हाल ही के एप्स"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धति बटन स्विच करें."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"संगतता ज़ूम बटन."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"छोटी से बड़ी स्क्रीन पर ज़ूम करें."</string>
@@ -144,7 +144,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारिज की गई."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना शेड."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"त्वरित सेटिंग."</string>
- <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"हाल ही के एप्लिकेशन."</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"हाल ही के एप्स."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"उपयोगकर्ता <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"मोबाइल <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
@@ -164,7 +164,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा सेट किया गया स्थान"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोध सक्रिय"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
- <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"एप्लिकेशन जानकारी"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"एप्स जानकारी"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रीन स्वचालित रूप से घूमेगी."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"स्क्रीन लैंडस्केप अभिविन्यास में लॉक है."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"स्क्रीन पोर्ट्रेट अभिविन्यास में लॉक है."</string>
diff --git a/packages/SystemUI/res/values-hy-rAM-land/strings.xml b/packages/SystemUI/res/values-hy-rAM-land/strings.xml
new file mode 100644
index 0000000..7c0535c
--- /dev/null
+++ b/packages/SystemUI/res/values-hy-rAM-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Էկրանն այժմ կողպված է հորիզոնական դիրքավորման մեջ:"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE-land/strings.xml b/packages/SystemUI/res/values-ka-rGE-land/strings.xml
new file mode 100644
index 0000000..3f20938
--- /dev/null
+++ b/packages/SystemUI/res/values-ka-rGE-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"ეკრანი ამჟამად დაბლოკილია თარაზულ ორიენტაციაში"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-km-rKH-land/strings.xml b/packages/SystemUI/res/values-km-rKH-land/strings.xml
new file mode 100644
index 0000000..f148cc3
--- /dev/null
+++ b/packages/SystemUI/res/values-km-rKH-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"ឥឡូវអេក្រង់ជាប់សោក្នុងទិសផ្ដេក។"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA-land/strings.xml b/packages/SystemUI/res/values-lo-rLA-land/strings.xml
new file mode 100644
index 0000000..a838a15
--- /dev/null
+++ b/packages/SystemUI/res/values-lo-rLA-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"ໜ້າຈໍຕອນນີ້ຖືກລັອກໄວ້ໃນແບບລວງນອນ."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN-land/strings.xml b/packages/SystemUI/res/values-mn-rMN-land/strings.xml
new file mode 100644
index 0000000..ec4616f
--- /dev/null
+++ b/packages/SystemUI/res/values-mn-rMN-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Дэлгэц хэвтээ чиглэлд түгжигдсэн."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY-land/strings.xml b/packages/SystemUI/res/values-ms-rMY-land/strings.xml
new file mode 100644
index 0000000..175b0fa
--- /dev/null
+++ b/packages/SystemUI/res/values-ms-rMY-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Skrin kini dikunci dalam orientasi landskap."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP-land/strings.xml b/packages/SystemUI/res/values-ne-rNP-land/strings.xml
new file mode 100644
index 0000000..8d5286e
--- /dev/null
+++ b/packages/SystemUI/res/values-ne-rNP-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"स्क्रिन अहिले ल्यान्डस्केप अवस्थामा बन्द छ।"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 19e2744..9e6605e 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -38,7 +38,7 @@
<string name="invalid_charger" msgid="4549105996740522523">"USB चार्ज गर्न समर्थित छैन।\n आपूर्ति गरिएको चार्जर मात्र प्रयोग गर्नुहोस्।"</string>
<string name="battery_low_why" msgid="7279169609518386372">"ब्याट्रि प्रयोग"</string>
<string name="status_bar_settings_settings_button" msgid="3023889916699270224">"सेटिङहरू"</string>
- <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"वाइ-फाइ"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"वाइफाइ"</string>
<string name="status_bar_settings_airplane" msgid="4879879698500955300">"हवाइजहाज मोड"</string>
<string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्वत:घुम्ने स्क्रिन"</string>
<string name="status_bar_settings_mute_label" msgid="554682549917429396">"म्युट गर्नुहोस्"</string>
@@ -127,9 +127,9 @@
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"रोमिङ"</string>
<string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
- <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"वाइ-फाइ"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"वाइफाइ"</string>
<string name="accessibility_no_sim" msgid="8274017118472455155">"SIM छैन।"</string>
- <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ब्लुटुथ टिथर गर्दै।"</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ब्लुटुथ टेदर गर्दै।"</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"हवाइजहाज मोड।"</string>
<string name="accessibility_battery_level" msgid="7451474187113371965">"ब्याट्रि <xliff:g id="NUMBER">%d</xliff:g> प्रतिशत"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"प्रणाली सेटिङहरू"</string>
@@ -159,7 +159,7 @@
<string name="data_usage_disabled_dialog" msgid="3853117269051806280">"तपाईँ निर्दिष्ट डेटा उपयोग सीमामा पुग्नु भएको छ।\n\nयदि तपाईँले डेटालाई पुनःसक्षम पार्नु भयो भने तपाईँलाई अर्को संचालकबाट शुल्क लगाउन सक्छ।"</string>
<string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"डेटा पुनः सक्षम गर्नुहोस्"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"इन्टरनेट जडान छैन"</string>
- <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"वाइ-फाइ जडित"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"वाइफाइ जडित"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSको लागि खोजी गर्दै"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा स्थान सेट गरिएको"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोधहरू सक्रिय"</string>
@@ -189,11 +189,11 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"सेटिङहरू"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"समय"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"मलाई"</string>
- <string name="quick_settings_wifi_label" msgid="9135344704899546041">"वाइ-फाइ"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"वाइफाइ"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"जोडिएको छैन"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"नेटवर्क छैन"</string>
- <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"वाइ-फाइ बन्द"</string>
- <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"वाइ-फाइ प्रदर्शन"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"वाइफाइ बन्द"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"वाइफाइ प्रदर्शन"</string>
<string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"ताररहित प्रदर्शन"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"उज्यालपन"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वतः"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 520ffb4..2c469b4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -185,7 +185,7 @@
<string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Автоповорот"</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Автоповорот выкл."</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Способ ввода"</string>
- <string name="quick_settings_location_label" msgid="5011327048748762257">"Местоположение"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Передача геоданных"</string>
<string name="quick_settings_location_off_label" msgid="7464544086507331459">"Местоположение выкл."</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Режим медиа"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
diff --git a/packages/SystemUI/res/values-si-rLK-land/strings.xml b/packages/SystemUI/res/values-si-rLK-land/strings.xml
new file mode 100644
index 0000000..b5aba2a
--- /dev/null
+++ b/packages/SystemUI/res/values-si-rLK-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"තිරය දැන් තිරස් දිශානතිය අගුළු දමා ඇත."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index d3ac4c2..f911f27 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -179,7 +179,7 @@
<string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Zungusha Otomatiki"</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Mzunguko Umefungwa"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Mbinu ya uingizaji"</string>
- <string name="quick_settings_location_label" msgid="5011327048748762257">"Eneo"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Kutambua Eneo"</string>
<string name="quick_settings_location_off_label" msgid="7464544086507331459">"Eneo Limezimwa"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Kifaa cha midia"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK-land/strings.xml b/packages/SystemUI/res/values-zh-rHK-land/strings.xml
new file mode 100644
index 0000000..8d55df4
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rHK-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"屏幕現已鎖定為橫向模式"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4dfad2f..6bf89e8 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -24,10 +24,10 @@
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Susa ohlwini"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Ulwazi lwensiza"</string>
<string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Azikho izinhlelo zokusebenza zakamuva"</string>
- <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Susa izinsiza zakamumva"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Susa izinhlelo zokusebenza zakamumva"</string>
<plurals name="status_bar_accessibility_recent_apps">
<item quantity="one" msgid="5854176083865845541">"Insiza eyi-1 yakamumva"</item>
- <item quantity="other" msgid="1040784359794890744">"%d izinsiza zakamumva"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d izinhlelo zokusebenza zakamumva"</item>
</plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Azikho izaziso"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Okuqhubekayo"</string>
@@ -47,11 +47,11 @@
<string name="bluetooth_tethered" msgid="7094101612161133267">"Ukusebenzisa i-Bluetooth njengemodemu"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Izilungiselelo zezindlela zokufakwayo"</string>
<string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Ukwakheka kwekhibhodi"</string>
- <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vumela insiza <xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ufinyelele ezintweni eziphuma ne-USB?"</string>
- <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vumela insiza <xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ufinyelele ezintweni eziphuma ne-USB?"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vumela uhlelo lokusebenza <xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ufinyelele ezintweni eziphuma ne-USB?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vumela uhlelo lokusebenza <xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ufinyelele ezintweni eziphuma ne-USB?"</string>
<string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vula <xliff:g id="ACTIVITY">%1$s</xliff:g> uma ledivayisi ye-USB ixhunyiwe?"</string>
<string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Vula <xliff:g id="ACTIVITY">%1$s</xliff:g> uma le-accessory ye-USB ixhunyiwe"</string>
- <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Azikho izinsiza ezisebenze ngezinto ze-USB. Funda okwengeziwe ngale into kwi <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Azikho izinhlelo zokusebenza ezisebenze ngezinto ze-USB. Funda okwengeziwe ngale into kwi <xliff:g id="URL">%1$s</xliff:g>"</string>
<string name="title_usb_accessory" msgid="4966265263465181372">"ama-accessory e-USB"</string>
<string name="label_view" msgid="6304565553218192990">"Buka"</string>
<string name="always_use_device" msgid="1450287437017315906">"Sebenzisa ngokuzenzakalelayo yale divayisi ye-USB"</string>
@@ -71,7 +71,7 @@
<string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Lengisa njengesidlali semediya (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Lengisa ikhamera (PTP)"</string>
- <string name="installer_cd_button_title" msgid="2312667578562201583">"Faka insiza yokudluliswa Kwefayela ye-Android kwi-Mac"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Faka uhlelo lokusebenza yokudluliswa Kwefayela ye-Android kwi-Mac"</string>
<string name="accessibility_back" msgid="567011538994429120">"Emuva"</string>
<string name="accessibility_home" msgid="8217216074895377641">"Ekhaya"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Imenyu"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 3946d1c..ada30ac 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -354,7 +354,6 @@
if (mPopup != null) {
mPopup.dismiss();
}
- ((RecentsActivity) mContext).moveTaskToBack(true);
}
}
diff --git a/packages/services/Proxy/com/android/net/IProxyCallback.aidl b/packages/services/Proxy/com/android/net/IProxyCallback.aidl
new file mode 100644
index 0000000..26b2a3f9
--- /dev/null
+++ b/packages/services/Proxy/com/android/net/IProxyCallback.aidl
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2013, 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.net;
+
+/** @hide */
+interface IProxyCallback
+{
+ oneway void getProxyPort(IBinder callback);
+}
diff --git a/packages/services/Proxy/com/android/net/IProxyPortListener.aidl b/packages/services/Proxy/com/android/net/IProxyPortListener.aidl
new file mode 100644
index 0000000..fa4caf3
--- /dev/null
+++ b/packages/services/Proxy/com/android/net/IProxyPortListener.aidl
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2013, 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.net;
+
+/** @hide */
+interface IProxyPortListener
+{
+ oneway void setProxyPort(int port);
+}
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
index 77f3c8c..4bf1db8 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
@@ -15,8 +15,11 @@
*/
package com.android.proxyhandler;
+import android.net.ProxyProperties;
+import android.os.RemoteException;
import android.util.Log;
+import com.android.net.IProxyPortListener;
import com.google.android.collect.Lists;
import java.io.IOException;
@@ -49,6 +52,8 @@
public boolean mIsRunning = false;
private ServerSocket serverSocket;
+ private int mPort;
+ private IProxyPortListener mCallback;
private class ProxyConnection implements Runnable {
private Socket connection;
@@ -179,33 +184,59 @@
public ProxyServer() {
threadExecutor = Executors.newCachedThreadPool();
+ mPort = -1;
+ mCallback = null;
}
@Override
public void run() {
try {
- serverSocket = new ServerSocket(ProxyService.PORT);
+ serverSocket = new ServerSocket(0);
- serverSocket.setReuseAddress(true);
+ if (serverSocket != null) {
+ setPort(serverSocket.getLocalPort());
- while (mIsRunning) {
- try {
- ProxyConnection parser = new ProxyConnection(serverSocket.accept());
+ while (mIsRunning) {
+ try {
+ ProxyConnection parser = new ProxyConnection(serverSocket.accept());
- threadExecutor.execute(parser);
- } catch (IOException e) {
- e.printStackTrace();
+ threadExecutor.execute(parser);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
} catch (SocketException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
+ Log.e(TAG, "Failed to start proxy server", e);
+ } catch (IOException e1) {
+ Log.e(TAG, "Failed to start proxy server", e1);
}
mIsRunning = false;
}
+ public synchronized void setPort(int port) {
+ if (mCallback != null) {
+ try {
+ mCallback.setProxyPort(port);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Proxy failed to report port to PacManager", e);
+ }
+ }
+ mPort = port;
+ }
+
+ public synchronized void setCallback(IProxyPortListener callback) {
+ if (mPort != -1) {
+ try {
+ callback.setProxyPort(mPort);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Proxy failed to report port to PacManager", e);
+ }
+ }
+ mCallback = callback;
+ }
+
public synchronized void startServer() {
mIsRunning = true;
start();
@@ -222,4 +253,12 @@
}
}
}
+
+ public boolean isBound() {
+ return (mPort != -1);
+ }
+
+ public int getPort() {
+ return mPort;
+ }
}
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
index cef3659..109435c 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
@@ -21,8 +21,12 @@
import android.net.ProxyProperties;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteException;
import android.text.TextUtils;
+import com.android.net.IProxyCallback;
+import com.android.net.IProxyPortListener;
+
/**
* @hide
*/
@@ -56,6 +60,16 @@
@Override
public IBinder onBind(Intent intent) {
- return null;
+ return new IProxyCallback.Stub() {
+ @Override
+ public void getProxyPort(IBinder callback) throws RemoteException {
+ if (server != null) {
+ IProxyPortListener portListener = IProxyPortListener.Stub.asInterface(callback);
+ if (portListener != null) {
+ server.setCallback(portListener);
+ }
+ }
+ }
+ };
}
}
\ No newline at end of file
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 3f8d7eb..19b762d 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -3463,7 +3463,7 @@
private void sendProxyBroadcast(ProxyProperties proxy) {
if (proxy == null) proxy = new ProxyProperties("", 0, "");
- mPacManager.setCurrentProxyScriptUrl(proxy);
+ if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
if (DBG) log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
@@ -3987,40 +3987,6 @@
// Start off with notification off
setProvNotificationVisible(false, ConnectivityManager.TYPE_NONE, null, null);
- // See if we've alreadying determined if we've got a provsioning connection
- // if so we don't need to do anything active
- MobileDataStateTracker mdstDefault = (MobileDataStateTracker)
- mNetTrackers[ConnectivityManager.TYPE_MOBILE];
- boolean isDefaultProvisioning = mdstDefault.isProvisioningNetwork();
-
- MobileDataStateTracker mdstHipri = (MobileDataStateTracker)
- mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
- boolean isHipriProvisioning = mdstHipri.isProvisioningNetwork();
-
- if (isDefaultProvisioning || isHipriProvisioning) {
- if (mIsNotificationVisible) {
- if (DBG) {
- log("checkMobileProvisioning: provisioning-ignore notification is visible");
- }
- } else {
- NetworkInfo ni = null;
- if (isDefaultProvisioning) {
- ni = mdstDefault.getNetworkInfo();
- }
- if (isHipriProvisioning) {
- ni = mdstHipri.getNetworkInfo();
- }
- String url = getMobileProvisioningUrl();
- if ((ni != null) && (!TextUtils.isEmpty(url))) {
- setProvNotificationVisible(true, ni.getType(), ni.getExtraInfo(), url);
- } else {
- if (DBG) log("checkMobileProvisioning: provisioning but no url, ignore");
- }
- }
- mIsCheckingMobileProvisioning.set(false);
- return timeOutMs;
- }
-
CheckMp checkMp = new CheckMp(mContext, this);
CheckMp.CallBack cb = new CheckMp.CallBack() {
@Override
@@ -4154,8 +4120,26 @@
mParams = params;
if (mCs.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {
- log("isMobileOk: not mobile capable");
result = CMP_RESULT_CODE_NO_CONNECTION;
+ log("isMobileOk: X not mobile capable result=" + result);
+ return result;
+ }
+
+ // See if we've already determined we've got a provisioning connection,
+ // if so we don't need to do anything active.
+ MobileDataStateTracker mdstDefault = (MobileDataStateTracker)
+ mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE];
+ boolean isDefaultProvisioning = mdstDefault.isProvisioningNetwork();
+ log("isMobileOk: isDefaultProvisioning=" + isDefaultProvisioning);
+
+ MobileDataStateTracker mdstHipri = (MobileDataStateTracker)
+ mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
+ boolean isHipriProvisioning = mdstHipri.isProvisioningNetwork();
+ log("isMobileOk: isHipriProvisioning=" + isHipriProvisioning);
+
+ if (isDefaultProvisioning || isHipriProvisioning) {
+ result = CMP_RESULT_CODE_PROVISIONING_NETWORK;
+ log("isMobileOk: X default || hipri is provisioning result=" + result);
return result;
}
@@ -4217,8 +4201,8 @@
MobileDataStateTracker mdst = (MobileDataStateTracker)
mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
if (mdst.isProvisioningNetwork()) {
- if (DBG) log("isMobileOk: isProvisioningNetwork is true");
result = CMP_RESULT_CODE_PROVISIONING_NETWORK;
+ if (DBG) log("isMobileOk: X isProvisioningNetwork result=" + result);
return result;
} else {
if (DBG) log("isMobileOk: isProvisioningNetwork is false, continue");
@@ -4233,8 +4217,8 @@
try {
addresses = InetAddress.getAllByName(orgUri.getHost());
} catch (UnknownHostException e) {
- log("isMobileOk: UnknownHostException");
result = CMP_RESULT_CODE_NO_DNS;
+ log("isMobileOk: X UnknownHostException result=" + result);
return result;
}
log("isMobileOk: addresses=" + inetAddressesToString(addresses));
@@ -4309,8 +4293,9 @@
if (responseCode == 204) {
// Return
- log("isMobileOk: expected responseCode=" + responseCode);
result = CMP_RESULT_CODE_CONNECTABLE;
+ log("isMobileOk: X expected responseCode=" + responseCode
+ + " result=" + result);
return result;
} else {
// Retry to be sure this was redirected, we've gotten
@@ -4328,7 +4313,7 @@
}
}
}
- log("isMobileOk: loops|timed out result=" + result);
+ log("isMobileOk: X loops|timed out result=" + result);
return result;
} catch (Exception e) {
log("isMobileOk: Exception e=" + e);
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 4521037..b4d9da0 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -328,8 +328,17 @@
addToStarting = true;
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Not delaying, but counting as bg: " + r);
} else if (DEBUG_DELAYED_STATS) {
- Slog.v(TAG, "Not potential delay (state=" + proc.curProcState
- + " " + proc.makeAdjReason() + "): " + r);
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("Not potential delay (state=").append(proc.curProcState)
+ .append(' ').append(proc.adjType);
+ String reason = proc.makeAdjReason();
+ if (reason != null) {
+ sb.append(' ');
+ sb.append(reason);
+ }
+ sb.append("): ");
+ sb.append(r.toString());
+ Slog.v(TAG, sb.toString());
}
} else if (DEBUG_DELAYED_STATS) {
if (callerFg) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 96b7030..e208f10 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1370,64 +1370,167 @@
break;
}
case REPORT_MEM_USAGE: {
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
- if (!isDebuggable) {
- return;
- }
- synchronized (ActivityManagerService.this) {
- long now = SystemClock.uptimeMillis();
- if (now < (mLastMemUsageReportTime+5*60*1000)) {
- // Don't report more than every 5 minutes to somewhat
- // avoid spamming.
- return;
- }
- mLastMemUsageReportTime = now;
- }
+ final ArrayList<ProcessMemInfo> memInfos = (ArrayList<ProcessMemInfo>)msg.obj;
Thread thread = new Thread() {
@Override public void run() {
- StringBuilder dropBuilder = new StringBuilder(1024);
+ final SparseArray<ProcessMemInfo> infoMap
+ = new SparseArray<ProcessMemInfo>(memInfos.size());
+ for (int i=0, N=memInfos.size(); i<N; i++) {
+ ProcessMemInfo mi = memInfos.get(i);
+ infoMap.put(mi.pid, mi);
+ }
+ updateCpuStatsNow();
+ synchronized (mProcessCpuThread) {
+ final int N = mProcessCpuTracker.countStats();
+ for (int i=0; i<N; i++) {
+ ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
+ if (st.vsize > 0) {
+ long pss = Debug.getPss(st.pid, null);
+ if (pss > 0) {
+ if (infoMap.indexOfKey(st.pid) < 0) {
+ ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
+ ProcessList.NATIVE_ADJ, -1, "native", null);
+ mi.pss = pss;
+ memInfos.add(mi);
+ }
+ }
+ }
+ }
+ }
+
+ long totalPss = 0;
+ for (int i=0, N=memInfos.size(); i<N; i++) {
+ ProcessMemInfo mi = memInfos.get(i);
+ if (mi.pss == 0) {
+ mi.pss = Debug.getPss(mi.pid, null);
+ }
+ totalPss += mi.pss;
+ }
+ Collections.sort(memInfos, new Comparator<ProcessMemInfo>() {
+ @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) {
+ if (lhs.oomAdj != rhs.oomAdj) {
+ return lhs.oomAdj < rhs.oomAdj ? -1 : 1;
+ }
+ if (lhs.pss != rhs.pss) {
+ return lhs.pss < rhs.pss ? 1 : -1;
+ }
+ return 0;
+ }
+ });
+
+ StringBuilder tag = new StringBuilder(128);
+ StringBuilder stack = new StringBuilder(128);
+ tag.append("Low on memory -- ");
+ appendMemBucket(tag, totalPss, "total", false);
+ appendMemBucket(stack, totalPss, "total", true);
+
StringBuilder logBuilder = new StringBuilder(1024);
+ logBuilder.append("Low on memory:\n");
+
+ boolean firstLine = true;
+ int lastOomAdj = Integer.MIN_VALUE;
+ for (int i=0, N=memInfos.size(); i<N; i++) {
+ ProcessMemInfo mi = memInfos.get(i);
+
+ if (mi.oomAdj != ProcessList.NATIVE_ADJ
+ && (mi.oomAdj < ProcessList.SERVICE_ADJ
+ || mi.oomAdj == ProcessList.HOME_APP_ADJ
+ || mi.oomAdj == ProcessList.PREVIOUS_APP_ADJ)) {
+ if (lastOomAdj != mi.oomAdj) {
+ lastOomAdj = mi.oomAdj;
+ if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
+ tag.append(" / ");
+ }
+ if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+ if (firstLine) {
+ stack.append(":");
+ firstLine = false;
+ }
+ stack.append("\n\t at ");
+ } else {
+ stack.append("$");
+ }
+ } else {
+ tag.append(" ");
+ stack.append("$");
+ }
+ if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
+ appendMemBucket(tag, mi.pss, mi.name, false);
+ }
+ appendMemBucket(stack, mi.pss, mi.name, true);
+ if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ
+ && ((i+1) >= N || memInfos.get(i+1).oomAdj != lastOomAdj)) {
+ stack.append("(");
+ for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
+ if (DUMP_MEM_OOM_ADJ[k] == mi.oomAdj) {
+ stack.append(DUMP_MEM_OOM_LABEL[k]);
+ stack.append(":");
+ stack.append(DUMP_MEM_OOM_ADJ[k]);
+ }
+ }
+ stack.append(")");
+ }
+ }
+
+ logBuilder.append(" ");
+ logBuilder.append(ProcessList.makeOomAdjString(mi.oomAdj));
+ logBuilder.append(' ');
+ logBuilder.append(ProcessList.makeProcStateString(mi.procState));
+ logBuilder.append(' ');
+ ProcessList.appendRamKb(logBuilder, mi.pss);
+ logBuilder.append(" kB: ");
+ logBuilder.append(mi.name);
+ logBuilder.append(" (");
+ logBuilder.append(mi.pid);
+ logBuilder.append(") ");
+ logBuilder.append(mi.adjType);
+ logBuilder.append('\n');
+ if (mi.adjReason != null) {
+ logBuilder.append(" ");
+ logBuilder.append(mi.adjReason);
+ logBuilder.append('\n');
+ }
+ }
+
+ logBuilder.append(" ");
+ ProcessList.appendRamKb(logBuilder, totalPss);
+ logBuilder.append(" kB: TOTAL\n");
+
+ long[] infos = new long[Debug.MEMINFO_COUNT];
+ Debug.getMemInfo(infos);
+ logBuilder.append(" MemInfo: ");
+ logBuilder.append(infos[Debug.MEMINFO_SLAB]).append(" kB slab, ");
+ logBuilder.append(infos[Debug.MEMINFO_SHMEM]).append(" kB shmem, ");
+ logBuilder.append(infos[Debug.MEMINFO_BUFFERS]).append(" kB buffers, ");
+ logBuilder.append(infos[Debug.MEMINFO_CACHED]).append(" kB cached, ");
+ logBuilder.append(infos[Debug.MEMINFO_FREE]).append(" kB free\n");
+
+ Slog.i(TAG, logBuilder.toString());
+
+ StringBuilder dropBuilder = new StringBuilder(1024);
+ /*
StringWriter oomSw = new StringWriter();
PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256);
StringWriter catSw = new StringWriter();
PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
String[] emptyArgs = new String[] { };
- StringBuilder tag = new StringBuilder(128);
- StringBuilder stack = new StringBuilder(128);
- tag.append("Low on memory -- ");
- dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw,
- tag, stack);
+ dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw);
+ oomPw.flush();
+ String oomString = oomSw.toString();
+ */
dropBuilder.append(stack);
dropBuilder.append('\n');
dropBuilder.append('\n');
- oomPw.flush();
- String oomString = oomSw.toString();
+ dropBuilder.append(logBuilder);
+ dropBuilder.append('\n');
+ /*
dropBuilder.append(oomString);
dropBuilder.append('\n');
- logBuilder.append(oomString);
- try {
- java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
- "procrank", });
- final InputStreamReader converter = new InputStreamReader(
- proc.getInputStream());
- BufferedReader in = new BufferedReader(converter);
- String line;
- while (true) {
- line = in.readLine();
- if (line == null) {
- break;
- }
- if (line.length() > 0) {
- logBuilder.append(line);
- logBuilder.append('\n');
- }
- dropBuilder.append(line);
- dropBuilder.append('\n');
- }
- converter.close();
- } catch (IOException e) {
- }
+ */
+ StringWriter catSw = new StringWriter();
synchronized (ActivityManagerService.this) {
+ PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
+ String[] emptyArgs = new String[] { };
catPw.println();
dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
catPw.println();
@@ -1435,12 +1538,13 @@
false, false, null);
catPw.println();
dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
+ catPw.flush();
}
- catPw.flush();
dropBuilder.append(catSw.toString());
addErrorToDropBox("lowmem", null, "system_server", null,
null, tag.toString(), dropBuilder.toString(), null, null);
- Slog.i(TAG, logBuilder.toString());
+ //Slog.i(TAG, "Sent to dropbox:");
+ //Slog.i(TAG, dropBuilder.toString());
synchronized (ActivityManagerService.this) {
long now = SystemClock.uptimeMillis();
if (mLastMemUsageReportTime < now) {
@@ -1691,8 +1795,7 @@
return;
}
- mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args,
- false, null, null, null);
+ mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null);
}
}
@@ -2466,10 +2569,17 @@
}
}
- String getHomePackageName() {
+ Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
- intent.addCategory(Intent.CATEGORY_HOME);
+ if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+ intent.addCategory(Intent.CATEGORY_HOME);
+ }
+ return intent;
+ }
+
+ String getHomePackageName() {
+ Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, mCurrentUserId);
if (aInfo != null) {
final String homePackageName = aInfo.applicationInfo.packageName;
@@ -2495,13 +2605,7 @@
// error message and don't try to start anything.
return false;
}
- Intent intent = new Intent(
- mTopAction,
- mTopData != null ? Uri.parse(mTopData) : null);
- intent.setComponent(mTopComponent);
- if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
- intent.addCategory(Intent.CATEGORY_HOME);
- }
+ Intent intent = getHomeIntent();
ActivityInfo aInfo =
resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
@@ -3271,6 +3375,66 @@
return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
}
+ final void doLowMemReportIfNeededLocked(ProcessRecord dyingProc) {
+ // If there are no longer any background processes running,
+ // and the app that died was not running instrumentation,
+ // then tell everyone we are now low on memory.
+ boolean haveBg = false;
+ for (int i=mLruProcesses.size()-1; i>=0; i--) {
+ ProcessRecord rec = mLruProcesses.get(i);
+ if (rec.thread != null
+ && rec.setProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
+ haveBg = true;
+ break;
+ }
+ }
+
+ if (!haveBg) {
+ boolean doReport = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
+ if (doReport) {
+ long now = SystemClock.uptimeMillis();
+ if (now < (mLastMemUsageReportTime+5*60*1000)) {
+ doReport = false;
+ } else {
+ mLastMemUsageReportTime = now;
+ }
+ }
+ final ArrayList<ProcessMemInfo> memInfos
+ = doReport ? new ArrayList<ProcessMemInfo>(mLruProcesses.size()) : null;
+ EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
+ long now = SystemClock.uptimeMillis();
+ for (int i=mLruProcesses.size()-1; i>=0; i--) {
+ ProcessRecord rec = mLruProcesses.get(i);
+ if (rec == dyingProc || rec.thread == null) {
+ continue;
+ }
+ if (doReport) {
+ memInfos.add(new ProcessMemInfo(rec.processName, rec.pid, rec.setAdj,
+ rec.setProcState, rec.adjType, rec.makeAdjReason()));
+ }
+ if ((rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
+ // The low memory report is overriding any current
+ // state for a GC request. Make sure to do
+ // heavy/important/visible/foreground processes first.
+ if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
+ rec.lastRequestedGc = 0;
+ } else {
+ rec.lastRequestedGc = rec.lastLowMemory;
+ }
+ rec.reportLowMemory = true;
+ rec.lastLowMemory = now;
+ mProcessesToGc.remove(rec);
+ addProcessToGcListLocked(rec);
+ }
+ }
+ if (doReport) {
+ Message msg = mHandler.obtainMessage(REPORT_MEM_USAGE, memInfos);
+ mHandler.sendMessage(msg);
+ }
+ scheduleAppGcsLocked();
+ }
+ }
+
final void appDiedLocked(ProcessRecord app, int pid,
IApplicationThread thread) {
@@ -3296,42 +3460,7 @@
handleAppDiedLocked(app, false, true);
if (doLowMem) {
- // If there are no longer any background processes running,
- // and the app that died was not running instrumentation,
- // then tell everyone we are now low on memory.
- boolean haveBg = false;
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord rec = mLruProcesses.get(i);
- if (rec.thread != null && rec.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
- haveBg = true;
- break;
- }
- }
-
- if (!haveBg) {
- EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
- long now = SystemClock.uptimeMillis();
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord rec = mLruProcesses.get(i);
- if (rec != app && rec.thread != null &&
- (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
- // The low memory report is overriding any current
- // state for a GC request. Make sure to do
- // heavy/important/visible/foreground processes first.
- if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
- rec.lastRequestedGc = 0;
- } else {
- rec.lastRequestedGc = rec.lastLowMemory;
- }
- rec.reportLowMemory = true;
- rec.lastLowMemory = now;
- mProcessesToGc.remove(rec);
- addProcessToGcListLocked(rec);
- }
- }
- mHandler.sendEmptyMessage(REPORT_MEM_USAGE);
- scheduleAppGcsLocked();
- }
+ doLowMemReportIfNeededLocked(app);
}
} else if (app.pid != pid) {
// A new process has already been started.
@@ -3850,6 +3979,8 @@
for (int i=0; i<N; i++) {
removeProcessLocked(procs.get(i), false, true, "kill all background");
}
+ updateOomAdjLocked();
+ doLowMemReportIfNeededLocked(null);
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -4159,6 +4290,7 @@
for (int i=0; i<N; i++) {
removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
}
+ updateOomAdjLocked();
return N > 0;
}
@@ -10791,14 +10923,6 @@
}
}
- private static String buildOomTag(String prefix, String space, int val, int base) {
- if (val == base) {
- if (space == null) return prefix;
- return prefix + " ";
- }
- return prefix + "+" + Integer.toString(val-base);
- }
-
private static final int dumpProcessList(PrintWriter pw,
ActivityManagerService service, List list,
String prefix, String normalLabel, String persistentLabel,
@@ -10870,34 +10994,7 @@
for (int i=list.size()-1; i>=0; i--) {
ProcessRecord r = list.get(i).first;
- String oomAdj;
- if (r.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
- oomAdj = buildOomTag("cch", " ", r.setAdj, ProcessList.CACHED_APP_MIN_ADJ);
- } else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
- oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
- } else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
- oomAdj = buildOomTag("prev ", null, r.setAdj, ProcessList.PREVIOUS_APP_ADJ);
- } else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
- oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
- } else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
- oomAdj = buildOomTag("svc ", null, r.setAdj, ProcessList.SERVICE_ADJ);
- } else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
- oomAdj = buildOomTag("hvy ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
- } else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
- oomAdj = buildOomTag("bkup ", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
- } else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
- oomAdj = buildOomTag("prcp ", null, r.setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
- } else if (r.setAdj >= ProcessList.VISIBLE_APP_ADJ) {
- oomAdj = buildOomTag("vis ", null, r.setAdj, ProcessList.VISIBLE_APP_ADJ);
- } else if (r.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
- oomAdj = buildOomTag("fore ", null, r.setAdj, ProcessList.FOREGROUND_APP_ADJ);
- } else if (r.setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
- oomAdj = buildOomTag("pers ", null, r.setAdj, ProcessList.PERSISTENT_PROC_ADJ);
- } else if (r.setAdj >= ProcessList.SYSTEM_ADJ) {
- oomAdj = buildOomTag("sys ", null, r.setAdj, ProcessList.SYSTEM_ADJ);
- } else {
- oomAdj = Integer.toString(r.setAdj);
- }
+ String oomAdj = ProcessList.makeOomAdjString(r.setAdj);
char schedGroup;
switch (r.setSchedGroup) {
case Process.THREAD_GROUP_BG_NONINTERACTIVE:
@@ -10918,54 +11015,7 @@
} else {
foreground = ' ';
}
- String procState;
- switch (r.curProcState) {
- case ActivityManager.PROCESS_STATE_PERSISTENT:
- procState = "P ";
- break;
- case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
- procState = "PU";
- break;
- case ActivityManager.PROCESS_STATE_TOP:
- procState = "T ";
- break;
- case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
- procState = "IF";
- break;
- case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
- procState = "IB";
- break;
- case ActivityManager.PROCESS_STATE_BACKUP:
- procState = "BU";
- break;
- case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
- procState = "HW";
- break;
- case ActivityManager.PROCESS_STATE_SERVICE:
- procState = "S ";
- break;
- case ActivityManager.PROCESS_STATE_RECEIVER:
- procState = "R ";
- break;
- case ActivityManager.PROCESS_STATE_HOME:
- procState = "HO";
- break;
- case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
- procState = "LA";
- break;
- case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
- procState = "CA";
- break;
- case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
- procState = "Ca";
- break;
- case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
- procState = "CE";
- break;
- default:
- procState = "??";
- break;
- }
+ String procState = ProcessList.makeProcStateString(r.curProcState);
pw.print(prefix);
pw.print(r.persistent ? persistentLabel : normalLabel);
pw.print(" #");
@@ -11253,6 +11303,7 @@
}
static final int[] DUMP_MEM_OOM_ADJ = new int[] {
+ ProcessList.NATIVE_ADJ,
ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ,
ProcessList.BACKUP_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
@@ -11260,6 +11311,7 @@
ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.CACHED_APP_MAX_ADJ
};
static final String[] DUMP_MEM_OOM_LABEL = new String[] {
+ "Native",
"System", "Persistent", "Foreground",
"Visible", "Perceptible",
"Heavy Weight", "Backup",
@@ -11267,6 +11319,7 @@
"Previous", "B Services", "Cached"
};
static final String[] DUMP_MEM_OOM_COMPACT_LABEL = new String[] {
+ "native",
"sys", "pers", "fore",
"vis", "percept",
"heavy", "backup",
@@ -11275,8 +11328,7 @@
};
final void dumpApplicationMemoryUsage(FileDescriptor fd,
- PrintWriter pw, String prefix, String[] args, boolean brief,
- PrintWriter categoryPw, StringBuilder outTag, StringBuilder outStack) {
+ PrintWriter pw, String prefix, String[] args, boolean brief, PrintWriter categoryPw) {
boolean dumpDetails = false;
boolean dumpDalvik = false;
boolean oomOnly = false;
@@ -11337,6 +11389,7 @@
System.arraycopy(args, opti, innerArgs, 0, args.length-opti);
ArrayList<MemItem> procMems = new ArrayList<MemItem>();
+ final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
long nativePss=0, dalvikPss=0, otherPss=0;
long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
@@ -11404,6 +11457,7 @@
(hasActivities ? " / activities)" : ")"),
r.processName, myTotalPss, pid, hasActivities);
procMems.add(pssItem);
+ procMemsMap.put(pid, pssItem);
nativePss += mi.nativePss;
dalvikPss += mi.dalvikPss;
@@ -11434,6 +11488,48 @@
}
if (!isCheckinRequest && procs.size() > 1) {
+ // If we are showing aggregations, also look for native processes to
+ // include so that our aggregations are more accurate.
+ updateCpuStatsNow();
+ synchronized (mProcessCpuThread) {
+ final int N = mProcessCpuTracker.countStats();
+ for (int i=0; i<N; i++) {
+ ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
+ if (st.vsize > 0 && procMemsMap.indexOfKey(st.pid) < 0) {
+ if (mi == null) {
+ mi = new Debug.MemoryInfo();
+ }
+ if (!brief && !oomOnly) {
+ Debug.getMemoryInfo(st.pid, mi);
+ } else {
+ mi.nativePss = (int)Debug.getPss(st.pid, tmpLong);
+ mi.nativePrivateDirty = (int)tmpLong[0];
+ }
+
+ final long myTotalPss = mi.getTotalPss();
+ totalPss += myTotalPss;
+
+ MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
+ st.name, myTotalPss, st.pid, false);
+ procMems.add(pssItem);
+
+ nativePss += mi.nativePss;
+ dalvikPss += mi.dalvikPss;
+ otherPss += mi.otherPss;
+ for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
+ long mem = mi.getOtherPss(j);
+ miscPss[j] += mem;
+ otherPss -= mem;
+ }
+ oomPss[0] += myTotalPss;
+ if (oomProcs[0] == null) {
+ oomProcs[0] = new ArrayList<MemItem>();
+ }
+ oomProcs[0].add(pssItem);
+ }
+ }
+ }
+
ArrayList<MemItem> catMems = new ArrayList<MemItem>();
catMems.add(new MemItem("Native", "Native", nativePss, -1));
@@ -11456,68 +11552,6 @@
}
}
- if (outTag != null || outStack != null) {
- if (outTag != null) {
- appendMemBucket(outTag, totalPss, "total", false);
- }
- if (outStack != null) {
- appendMemBucket(outStack, totalPss, "total", true);
- }
- boolean firstLine = true;
- for (int i=0; i<oomMems.size(); i++) {
- MemItem miCat = oomMems.get(i);
- if (miCat.subitems == null || miCat.subitems.size() < 1) {
- continue;
- }
- if (miCat.id < ProcessList.SERVICE_ADJ
- || miCat.id == ProcessList.HOME_APP_ADJ
- || miCat.id == ProcessList.PREVIOUS_APP_ADJ) {
- if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
- outTag.append(" / ");
- }
- if (outStack != null) {
- if (miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
- if (firstLine) {
- outStack.append(":");
- firstLine = false;
- }
- outStack.append("\n\t at ");
- } else {
- outStack.append("$");
- }
- }
- for (int j=0; j<miCat.subitems.size(); j++) {
- MemItem memi = miCat.subitems.get(j);
- if (j > 0) {
- if (outTag != null) {
- outTag.append(" ");
- }
- if (outStack != null) {
- outStack.append("$");
- }
- }
- if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
- appendMemBucket(outTag, memi.pss, memi.shortLabel, false);
- }
- if (outStack != null) {
- appendMemBucket(outStack, memi.pss, memi.shortLabel, true);
- }
- }
- if (outStack != null && miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
- outStack.append("(");
- for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
- if (DUMP_MEM_OOM_ADJ[k] == miCat.id) {
- outStack.append(DUMP_MEM_OOM_LABEL[k]);
- outStack.append(":");
- outStack.append(DUMP_MEM_OOM_ADJ[k]);
- }
- }
- outStack.append(")");
- }
- }
- }
- }
-
if (!brief && !oomOnly && !isCompact) {
pw.println();
pw.println("Total PSS by process:");
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index e994c23..064b3a8 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2910,6 +2910,19 @@
mWindowManager.prepareAppTransition(transit, false);
}
+ void moveHomeTaskToTop() {
+ final int top = mTaskHistory.size() - 1;
+ for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = mTaskHistory.get(taskNdx);
+ if (task.isHomeTask()) {
+ mTaskHistory.remove(taskNdx);
+ mTaskHistory.add(top, task);
+ mWindowManager.moveTaskToTop(task.taskId);
+ return;
+ }
+ }
+ }
+
final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
final TaskRecord task = taskForIdLocked(taskId);
if (task != null) {
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 3e0b5eb..e0eb2c4 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -284,6 +284,7 @@
if (prev != null) {
prev.mLaunchHomeTaskNext = false;
}
+ mHomeStack.moveHomeTaskToTop();
ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
if (r != null) {
mService.setFocusedActivityLocked(r);
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index fb81b3a..54593aa 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -19,6 +19,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
+import android.app.ActivityManager;
import com.android.internal.util.MemInfoReader;
import com.android.server.wm.WindowManagerService;
@@ -98,6 +99,10 @@
// The system process runs at the default adjustment.
static final int SYSTEM_ADJ = -16;
+ // Special code for native processes that are not being managed by the system (so
+ // don't have an oom adj assigned by the system).
+ static final int NATIVE_ADJ = -17;
+
// Memory pages are 4K.
static final int PAGE_SIZE = 4*1024;
@@ -278,6 +283,46 @@
return (totalProcessLimit*2)/3;
}
+ private static String buildOomTag(String prefix, String space, int val, int base) {
+ if (val == base) {
+ if (space == null) return prefix;
+ return prefix + " ";
+ }
+ return prefix + "+" + Integer.toString(val-base);
+ }
+
+ public static String makeOomAdjString(int setAdj) {
+ if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
+ return buildOomTag("cch", " ", setAdj, ProcessList.CACHED_APP_MIN_ADJ);
+ } else if (setAdj >= ProcessList.SERVICE_B_ADJ) {
+ return buildOomTag("svcb ", null, setAdj, ProcessList.SERVICE_B_ADJ);
+ } else if (setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
+ return buildOomTag("prev ", null, setAdj, ProcessList.PREVIOUS_APP_ADJ);
+ } else if (setAdj >= ProcessList.HOME_APP_ADJ) {
+ return buildOomTag("home ", null, setAdj, ProcessList.HOME_APP_ADJ);
+ } else if (setAdj >= ProcessList.SERVICE_ADJ) {
+ return buildOomTag("svc ", null, setAdj, ProcessList.SERVICE_ADJ);
+ } else if (setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
+ return buildOomTag("hvy ", null, setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
+ } else if (setAdj >= ProcessList.BACKUP_APP_ADJ) {
+ return buildOomTag("bkup ", null, setAdj, ProcessList.BACKUP_APP_ADJ);
+ } else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
+ return buildOomTag("prcp ", null, setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
+ } else if (setAdj >= ProcessList.VISIBLE_APP_ADJ) {
+ return buildOomTag("vis ", null, setAdj, ProcessList.VISIBLE_APP_ADJ);
+ } else if (setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+ return buildOomTag("fore ", null, setAdj, ProcessList.FOREGROUND_APP_ADJ);
+ } else if (setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
+ return buildOomTag("pers ", null, setAdj, ProcessList.PERSISTENT_PROC_ADJ);
+ } else if (setAdj >= ProcessList.SYSTEM_ADJ) {
+ return buildOomTag("sys ", null, setAdj, ProcessList.SYSTEM_ADJ);
+ } else if (setAdj >= ProcessList.NATIVE_ADJ) {
+ return buildOomTag("ntv ", null, setAdj, ProcessList.NATIVE_ADJ);
+ } else {
+ return Integer.toString(setAdj);
+ }
+ }
+
// The minimum amount of time after a state change it is safe ro collect PSS.
public static final int PSS_MIN_TIME_FROM_STATE_CHANGE = 15*1000;
@@ -366,6 +411,70 @@
return sProcStateToProcMem[procState1] != sProcStateToProcMem[procState2];
}
+ public static String makeProcStateString(int curProcState) {
+ String procState;
+ switch (curProcState) {
+ case -1:
+ procState = "N ";
+ break;
+ case ActivityManager.PROCESS_STATE_PERSISTENT:
+ procState = "P ";
+ break;
+ case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
+ procState = "PU";
+ break;
+ case ActivityManager.PROCESS_STATE_TOP:
+ procState = "T ";
+ break;
+ case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
+ procState = "IF";
+ break;
+ case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
+ procState = "IB";
+ break;
+ case ActivityManager.PROCESS_STATE_BACKUP:
+ procState = "BU";
+ break;
+ case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
+ procState = "HW";
+ break;
+ case ActivityManager.PROCESS_STATE_SERVICE:
+ procState = "S ";
+ break;
+ case ActivityManager.PROCESS_STATE_RECEIVER:
+ procState = "R ";
+ break;
+ case ActivityManager.PROCESS_STATE_HOME:
+ procState = "HO";
+ break;
+ case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
+ procState = "LA";
+ break;
+ case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
+ procState = "CA";
+ break;
+ case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
+ procState = "Ca";
+ break;
+ case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
+ procState = "CE";
+ break;
+ default:
+ procState = "??";
+ break;
+ }
+ return procState;
+ }
+
+ public static void appendRamKb(StringBuilder sb, long ramKb) {
+ for (int j=0, fact=10; j<6; j++, fact*=10) {
+ if (ramKb < fact) {
+ sb.append(' ');
+ }
+ }
+ sb.append(ramKb);
+ }
+
public static long computeNextPssTime(int procState, boolean first, boolean sleeping,
long now) {
final long[] table = sleeping
diff --git a/services/java/com/android/server/am/ProcessMemInfo.java b/services/java/com/android/server/am/ProcessMemInfo.java
new file mode 100644
index 0000000..c94694e
--- /dev/null
+++ b/services/java/com/android/server/am/ProcessMemInfo.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+public class ProcessMemInfo {
+ final String name;
+ final int pid;
+ final int oomAdj;
+ final int procState;
+ final String adjType;
+ final String adjReason;
+ long pss;
+
+ public ProcessMemInfo(String _name, int _pid, int _oomAdj, int _procState,
+ String _adjType, String _adjReason) {
+ name = _name;
+ pid = _pid;
+ oomAdj = _oomAdj;
+ procState = _procState;
+ adjType = _adjType;
+ adjReason = _adjReason;
+ }
+}
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 892271f..35e06b6 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -529,9 +529,8 @@
}
public String makeAdjReason() {
- StringBuilder sb = new StringBuilder(128);
- sb.append('(').append(adjType).append(')');
if (adjSource != null || adjTarget != null) {
+ StringBuilder sb = new StringBuilder(128);
sb.append(' ');
if (adjTarget instanceof ComponentName) {
sb.append(((ComponentName)adjTarget).flattenToShortString());
@@ -550,8 +549,9 @@
} else {
sb.append("{null}");
}
+ return sb.toString();
}
- return sb.toString();
+ return null;
}
/*
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 63793fa..479665c 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -322,6 +322,10 @@
return subtask.activity;
}
+ boolean isHomeTask() {
+ return mTaskType == ActivityRecord.HOME_ACTIVITY_TYPE;
+ }
+
boolean isApplicationTask() {
return mTaskType == ActivityRecord.APPLICATION_ACTIVITY_TYPE;
}
diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java
index c8cc85e..772921a 100644
--- a/services/java/com/android/server/connectivity/PacManager.java
+++ b/services/java/com/android/server/connectivity/PacManager.java
@@ -24,17 +24,22 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.net.Proxy;
import android.net.ProxyProperties;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.net.IProxyCallback;
+import com.android.net.IProxyPortListener;
import com.android.net.IProxyService;
import com.android.server.IoThread;
@@ -79,6 +84,7 @@
private Context mContext;
private int mCurrentDelay;
+ private int mLastPort;
/**
* Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
@@ -119,6 +125,7 @@
public PacManager(Context context) {
mContext = context;
+ mLastPort = -1;
mPacRefreshIntent = PendingIntent.getBroadcast(
context, 0, new Intent(ACTION_PAC_REFRESH), 0);
@@ -133,7 +140,16 @@
return mAlarmManager;
}
- public synchronized void setCurrentProxyScriptUrl(ProxyProperties proxy) {
+ /**
+ * Updates the PAC Manager with current Proxy information. This is called by
+ * the ConnectivityService directly before a broadcast takes place to allow
+ * the PacManager to indicate that the broadcast should not be sent and the
+ * PacManager will trigger a new broadcast when it is ready.
+ *
+ * @param proxy Proxy information that is about to be broadcast.
+ * @return Returns true when the broadcast should not be sent
+ */
+ public synchronized boolean setCurrentProxyScriptUrl(ProxyProperties proxy) {
if (!TextUtils.isEmpty(proxy.getPacFileUrl())) {
synchronized (mProxyLock) {
mPacUrl = proxy.getPacFileUrl();
@@ -141,6 +157,7 @@
mCurrentDelay = DELAY_1;
getAlarmManager().cancel(mPacRefreshIntent);
bind();
+ return true;
} else {
getAlarmManager().cancel(mPacRefreshIntent);
synchronized (mProxyLock) {
@@ -156,6 +173,7 @@
}
}
}
+ return false;
}
}
@@ -233,6 +251,16 @@
}
Intent intent = new Intent();
intent.setClassName(PAC_PACKAGE, PAC_SERVICE);
+ // Already bound no need to bind again.
+ if (mProxyConnection != null) {
+ if (mLastPort != -1) {
+ sendPacBroadcast(new ProxyProperties(mPacUrl, mLastPort));
+ } else {
+ Log.e(TAG, "Received invalid port from Local Proxy,"
+ + " PAC will not be operational");
+ }
+ return;
+ }
mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName component) {
@@ -277,6 +305,26 @@
@Override
public void onServiceConnected(ComponentName component, IBinder binder) {
+ IProxyCallback callbackService = IProxyCallback.Stub.asInterface(binder);
+ if (callbackService != null) {
+ try {
+ callbackService.getProxyPort(new IProxyPortListener.Stub() {
+ @Override
+ public void setProxyPort(int port) throws RemoteException {
+ mLastPort = port;
+ if (port != -1) {
+ Log.d(TAG, "Local proxy is bound on " + port);
+ sendPacBroadcast(new ProxyProperties(mPacUrl, port));
+ } else {
+ Log.e(TAG, "Received invalid port from Local Proxy,"
+ + " PAC will not be operational");
+ }
+ }
+ });
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
}
};
mContext.bindService(intent, mProxyConnection,
@@ -287,5 +335,19 @@
mContext.unbindService(mConnection);
mContext.unbindService(mProxyConnection);
mConnection = null;
+ mProxyConnection = null;
+ }
+
+ private void sendPacBroadcast(ProxyProperties proxy) {
+ Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 686b64e..39fc4ad 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -9716,10 +9716,6 @@
throw new IllegalArgumentException(
"replacePreferredActivity expects filter to have only 1 action.");
}
- if (filter.countCategories() != 1) {
- throw new IllegalArgumentException(
- "replacePreferredActivity expects filter to have only 1 category.");
- }
if (filter.countDataAuthorities() != 0
|| filter.countDataPaths() != 0
|| filter.countDataSchemes() != 0
@@ -9756,8 +9752,11 @@
removed = new ArrayList<PreferredActivity>();
}
removed.add(pa);
- Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
- filter.dump(new LogPrinter(Log.INFO, TAG), " ");
+ if (DEBUG_PREFERRED) {
+ Slog.i(TAG, "Removing preferred activity "
+ + pa.mPref.mComponent + ":");
+ filter.dump(new LogPrinter(Log.INFO, TAG), " ");
+ }
}
}
if (removed != null) {
@@ -9877,6 +9876,28 @@
}
@Override
+ public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+
+ final int callingUserId = UserHandle.getCallingUserId();
+ List<ResolveInfo> list = queryIntentActivities(intent, null, 0, callingUserId);
+ ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
+ true, false, callingUserId);
+
+ allHomeCandidates.clear();
+ if (list != null) {
+ for (ResolveInfo ri : list) {
+ allHomeCandidates.add(ri);
+ }
+ }
+ return (preferred == null || preferred.activityInfo == null)
+ ? null
+ : new ComponentName(preferred.activityInfo.packageName,
+ preferred.activityInfo.name);
+ }
+
+ @Override
public void setApplicationEnabledSetting(String appPackageName,
int newState, int flags, int userId, String callingPackage) {
if (!sUserManager.exists(userId)) return;
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 4683534..5f944f6 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -46,6 +46,7 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Binder;
+import android.os.RemoteException;
import android.os.UserHandle;
import java.util.List;
@@ -543,6 +544,12 @@
throw new UnsupportedOperationException();
}
+ /** @hide - hidden in superclass */
+ @Override
+ public ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String[] getSystemSharedLibraryNames() {
throw new UnsupportedOperationException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
similarity index 62%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
index e0414fe..6c998af 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -16,7 +16,6 @@
package com.android.layoutlib.bridge.impl.binding;
-import com.android.ide.common.rendering.api.AdapterBinding;
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
@@ -27,7 +26,6 @@
import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.util.Pair;
-import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -35,124 +33,27 @@
import android.widget.ImageView;
import android.widget.TextView;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
/**
- * Base adapter to do fake data binding in {@link AdapterView} objects.
+ * A Helper class to do fake data binding in {@link AdapterView} objects.
*/
-public class BaseAdapter {
+@SuppressWarnings("deprecation")
+public class AdapterHelper {
- /**
- * This is the items provided by the adapter. They are dynamically generated.
- */
- protected final static class AdapterItem {
- private final DataBindingItem mItem;
- private final int mType;
- private final int mFullPosition;
- private final int mPositionPerType;
- private List<AdapterItem> mChildren;
-
- protected AdapterItem(DataBindingItem item, int type, int fullPosition,
- int positionPerType) {
- mItem = item;
- mType = type;
- mFullPosition = fullPosition;
- mPositionPerType = positionPerType;
- }
-
- void addChild(AdapterItem child) {
- if (mChildren == null) {
- mChildren = new ArrayList<AdapterItem>();
- }
-
- mChildren.add(child);
- }
-
- List<AdapterItem> getChildren() {
- if (mChildren != null) {
- return mChildren;
- }
-
- return Collections.emptyList();
- }
-
- int getType() {
- return mType;
- }
-
- int getFullPosition() {
- return mFullPosition;
- }
-
- int getPositionPerType() {
- return mPositionPerType;
- }
-
- DataBindingItem getDataBindingItem() {
- return mItem;
- }
- }
-
- private final AdapterBinding mBinding;
- private final IProjectCallback mCallback;
- private final ResourceReference mAdapterRef;
- private boolean mSkipCallbackParser = false;
-
- protected final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
-
- protected BaseAdapter(ResourceReference adapterRef, AdapterBinding binding,
- IProjectCallback callback) {
- mAdapterRef = adapterRef;
- mBinding = binding;
- mCallback = callback;
- }
-
- // ------- Some Adapter method used by all children classes.
-
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- public boolean hasStableIds() {
- return true;
- }
-
- public boolean isEmpty() {
- return mItems.size() == 0;
- }
-
- public void registerDataSetObserver(DataSetObserver observer) {
- // pass
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- // pass
- }
-
- // -------
-
-
- protected AdapterBinding getBinding() {
- return mBinding;
- }
-
- protected View getView(AdapterItem item, AdapterItem parentItem, View convertView,
- ViewGroup parent) {
+ static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
+ IProjectCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
// we don't care about recycling here because we never scroll.
DataBindingItem dataBindingItem = item.getDataBindingItem();
BridgeContext context = RenderAction.getCurrentContext();
Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(),
- parent, false /*attachToRoot*/, mSkipCallbackParser);
+ parent, false /*attachToRoot*/, skipCallbackParser);
View view = pair.getFirst();
- mSkipCallbackParser |= pair.getSecond();
+ skipCallbackParser |= pair.getSecond();
if (view != null) {
- fillView(context, view, item, parentItem);
+ fillView(context, view, item, parentItem, callback, adapterRef);
} else {
// create a text view to display an error.
TextView tv = new TextView(context);
@@ -160,16 +61,16 @@
view = tv;
}
- return view;
+ return Pair.of(view, skipCallbackParser);
}
- private void fillView(BridgeContext context, View view, AdapterItem item,
- AdapterItem parentItem) {
+ private static void fillView(BridgeContext context, View view, AdapterItem item,
+ AdapterItem parentItem, IProjectCallback callback, ResourceReference adapterRef) {
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
final int count = group.getChildCount();
for (int i = 0 ; i < count ; i++) {
- fillView(context, group.getChildAt(i), item, parentItem);
+ fillView(context, group.getChildAt(i), item, parentItem, callback, adapterRef);
}
} else {
int id = view.getId();
@@ -184,8 +85,8 @@
if (view instanceof TextView) {
TextView tv = (TextView) view;
- Object value = mCallback.getAdapterItemValue(
- mAdapterRef, context.getViewKey(view),
+ Object value = callback.getAdapterItemValue(
+ adapterRef, context.getViewKey(view),
item.getDataBindingItem().getViewReference(),
fullPosition, positionPerType,
fullParentPosition, parentPositionPerType,
@@ -204,8 +105,8 @@
if (view instanceof Checkable) {
Checkable cb = (Checkable) view;
- Object value = mCallback.getAdapterItemValue(
- mAdapterRef, context.getViewKey(view),
+ Object value = callback.getAdapterItemValue(
+ adapterRef, context.getViewKey(view),
item.getDataBindingItem().getViewReference(),
fullPosition, positionPerType,
fullParentPosition, parentPositionPerType,
@@ -224,8 +125,8 @@
if (view instanceof ImageView) {
ImageView iv = (ImageView) view;
- Object value = mCallback.getAdapterItemValue(
- mAdapterRef, context.getViewKey(view),
+ Object value = callback.getAdapterItemValue(
+ adapterRef, context.getViewKey(view),
item.getDataBindingItem().getViewReference(),
fullPosition, positionPerType,
fullParentPosition, parentPositionPerType,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java
new file mode 100644
index 0000000..8e28dba
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 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.layoutlib.bridge.impl.binding;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.android.ide.common.rendering.api.DataBindingItem;
+
+/**
+ * This is the items provided by the adapter. They are dynamically generated.
+ */
+final class AdapterItem {
+ private final DataBindingItem mItem;
+ private final int mType;
+ private final int mFullPosition;
+ private final int mPositionPerType;
+ private List<AdapterItem> mChildren;
+
+ protected AdapterItem(DataBindingItem item, int type, int fullPosition,
+ int positionPerType) {
+ mItem = item;
+ mType = type;
+ mFullPosition = fullPosition;
+ mPositionPerType = positionPerType;
+ }
+
+ void addChild(AdapterItem child) {
+ if (mChildren == null) {
+ mChildren = new ArrayList<AdapterItem>();
+ }
+
+ mChildren.add(child);
+ }
+
+ List<AdapterItem> getChildren() {
+ if (mChildren != null) {
+ return mChildren;
+ }
+
+ return Collections.emptyList();
+ }
+
+ int getType() {
+ return mType;
+ }
+
+ int getFullPosition() {
+ return mFullPosition;
+ }
+
+ int getPositionPerType() {
+ return mPositionPerType;
+ }
+
+ DataBindingItem getDataBindingItem() {
+ return mItem;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java
index 22570b9..9a13f5a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java
@@ -20,10 +20,12 @@
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.ResourceReference;
+import com.android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
+import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.SpinnerAdapter;
@@ -35,17 +37,23 @@
* and {@link SpinnerAdapter}.
*
*/
-public class FakeAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
+@SuppressWarnings("deprecation")
+public class FakeAdapter extends BaseAdapter {
// don't use a set because the order is important.
private final List<ResourceReference> mTypes = new ArrayList<ResourceReference>();
+ private final IProjectCallback mCallback;
+ private final ResourceReference mAdapterRef;
+ private final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
+ private boolean mSkipCallbackParser = false;
public FakeAdapter(ResourceReference adapterRef, AdapterBinding binding,
IProjectCallback callback) {
- super(adapterRef, binding, callback);
+ mAdapterRef = adapterRef;
+ mCallback = callback;
- final int repeatCount = getBinding().getRepeatCount();
- final int itemCount = getBinding().getItemCount();
+ final int repeatCount = binding.getRepeatCount();
+ final int itemCount = binding.getItemCount();
// Need an array to count for each type.
// This is likely too big, but is the max it can be.
@@ -54,7 +62,7 @@
// We put several repeating sets.
for (int r = 0 ; r < repeatCount ; r++) {
// loop on the type of list items, and add however many for each type.
- for (DataBindingItem dataBindingItem : getBinding()) {
+ for (DataBindingItem dataBindingItem : binding) {
ResourceReference viewRef = dataBindingItem.getViewReference();
int typeIndex = mTypes.indexOf(viewRef);
if (typeIndex == -1) {
@@ -103,7 +111,11 @@
public View getView(int position, View convertView, ViewGroup parent) {
// we don't care about recycling here because we never scroll.
AdapterItem item = mItems.get(position);
- return getView(item, null /*parentGroup*/, convertView, parent);
+ Pair<View, Boolean> pair = AdapterHelper.getView(item, null /*parentGroup*/, parent,
+ mCallback, mAdapterRef, mSkipCallbackParser);
+ mSkipCallbackParser = pair.getSecond();
+ return pair.getFirst();
+
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java
index 199e040..e539579 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java
@@ -20,7 +20,9 @@
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.ResourceReference;
+import com.android.util.Pair;
+import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListAdapter;
@@ -29,8 +31,14 @@
import java.util.ArrayList;
import java.util.List;
-public class FakeExpandableAdapter extends BaseAdapter implements ExpandableListAdapter,
- HeterogeneousExpandableList {
+@SuppressWarnings("deprecation")
+public class FakeExpandableAdapter implements ExpandableListAdapter, HeterogeneousExpandableList {
+
+ private final IProjectCallback mCallback;
+ private final ResourceReference mAdapterRef;
+ private boolean mSkipCallbackParser = false;
+
+ protected final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
// don't use a set because the order is important.
private final List<ResourceReference> mGroupTypes = new ArrayList<ResourceReference>();
@@ -38,7 +46,8 @@
public FakeExpandableAdapter(ResourceReference adapterRef, AdapterBinding binding,
IProjectCallback callback) {
- super(adapterRef, binding, callback);
+ mAdapterRef = adapterRef;
+ mCallback = callback;
createItems(binding, binding.getItemCount(), binding.getRepeatCount(), mGroupTypes, 1);
}
@@ -125,7 +134,10 @@
ViewGroup parent) {
// we don't care about recycling here because we never scroll.
AdapterItem item = mItems.get(groupPosition);
- return getView(item, null /*parentItem*/, convertView, parent);
+ Pair<View, Boolean> pair = AdapterHelper.getView(item, null /*parentItem*/, parent,
+ mCallback, mAdapterRef, mSkipCallbackParser);
+ mSkipCallbackParser = pair.getSecond();
+ return pair.getFirst();
}
@Override
@@ -134,7 +146,10 @@
// we don't care about recycling here because we never scroll.
AdapterItem parentItem = mItems.get(groupPosition);
AdapterItem item = getChildItem(groupPosition, childPosition);
- return getView(item, parentItem, convertView, parent);
+ Pair<View, Boolean> pair = AdapterHelper.getView(item, parentItem, parent, mCallback,
+ mAdapterRef, mSkipCallbackParser);
+ mSkipCallbackParser = pair.getSecond();
+ return pair.getFirst();
}
@Override
@@ -172,6 +187,31 @@
// pass
}
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ // pass
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ // pass
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mItems.isEmpty();
+ }
+
// ---- HeterogeneousExpandableList
@Override