diff options
Diffstat (limited to 'core/java/android')
62 files changed, 1682 insertions, 462 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 370db31..a727b07 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1995,6 +1995,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeParcelableArray(uris, 0); return true; } + + case PERFORM_IDLE_MAINTENANCE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + performIdleMaintenance(); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -4578,5 +4585,15 @@ class ActivityManagerProxy implements IActivityManager return uris; } + public void performIdleMaintenance() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(PERFORM_IDLE_MAINTENANCE_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + private IBinder mRemote; } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 3e4795c..bf2a1e4 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -65,7 +65,7 @@ public class AppOpsManager { // when adding one of these: // - increment _NUM_OP - // - add rows to sOpToSwitch, sOpNames, sOpPerms + // - add rows to sOpToSwitch, sOpNames, sOpPerms, sOpDefaultMode // - add descriptive strings to Settings/res/values/arrays.xml // - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app) @@ -315,6 +315,55 @@ public class AppOpsManager { }; /** + * This specifies the default mode for each operation. + */ + private static int[] sOpDefaultMode = new int[] { + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + }; + + /** * Retrieve the op switch that controls the given operation. * @hide */ @@ -339,6 +388,14 @@ public class AppOpsManager { } /** + * Retrieve the default mode for the operation. + * @hide + */ + public static int opToDefaultMode(int op) { + return sOpDefaultMode[op]; + } + + /** * Class holding all of the operation information associated with an app. * @hide */ diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index e522b78..55c6672 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1251,6 +1251,16 @@ final class ApplicationPackageManager extends PackageManager { } @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/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index b2ae298..25c02df 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -403,6 +403,8 @@ public interface IActivityManager extends IInterface { String sourcePackage, String targetPackage, int modeFlags, int modeMask) throws RemoteException; + public void performIdleMaintenance() throws RemoteException; + /* * Private non-Binder interfaces */ @@ -685,4 +687,5 @@ public interface IActivityManager extends IInterface { int REPORT_ACTIVITY_FULLY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+176; int RESTART_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+177; int GET_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+178; + int PERFORM_IDLE_MAINTENANCE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+179; } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 3342068..2bc7cbf 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -16,8 +16,11 @@ package android.app; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -30,7 +33,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.os.Binder; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -41,13 +44,13 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.DisplayMetrics; import android.util.Log; -import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.WindowManagerGlobal; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.List; /** * Provides access to the system wallpaper. With WallpaperManager, you can @@ -62,6 +65,15 @@ public class WallpaperManager { private float mWallpaperYStep = -1; /** + * Activity Action: Show settings for choosing wallpaper. Do not use directly to construct + * an intent; instead, use {@link #getCropAndSetWallpaperIntent}. + * <p>Input: {@link Intent#getData} is the URI of the image to crop and set as wallpaper. + * <p>Output: RESULT_OK if user decided to crop/set the wallpaper, RESULT_CANCEL otherwise + */ + public static final String ACTION_CROP_AND_SET_WALLPAPER = + "android.service.wallpaper.CROP_AND_SET_WALLPAPER"; + + /** * Launch an activity for the user to pick the current global live * wallpaper. */ @@ -463,7 +475,39 @@ public class WallpaperManager { return null; } } - + + /** + * Gets an Intent that will launch an activity that crops the given + * image and sets the device's wallpaper. If there is a default HOME activity + * that supports cropping wallpapers, it will be preferred as the default. + * Use this method instead of directly creating a {@link #ACTION_CROP_AND_SET_WALLPAPER} + * intent. + */ + public Intent getCropAndSetWallpaperIntent(Uri imageUri) { + final PackageManager packageManager = mContext.getPackageManager(); + Intent cropAndSetWallpaperIntent = + new Intent(ACTION_CROP_AND_SET_WALLPAPER, imageUri); + cropAndSetWallpaperIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + // Find out if the default HOME activity supports CROP_AND_SET_WALLPAPER + Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME); + ResolveInfo resolvedHome = packageManager.resolveActivity(homeIntent, + PackageManager.MATCH_DEFAULT_ONLY); + if (resolvedHome != null) { + cropAndSetWallpaperIntent.setPackage(resolvedHome.activityInfo.packageName); + + List<ResolveInfo> cropAppList = packageManager.queryIntentActivities( + cropAndSetWallpaperIntent, 0); + if (cropAppList.size() > 0) { + return cropAndSetWallpaperIntent; + } + } + + // fallback crop activity + cropAndSetWallpaperIntent.setPackage("com.android.wallpapercropper"); + return cropAndSetWallpaperIntent; + } + /** * Change the current system wallpaper to the bitmap in the given resource. * The resource is opened as a raw data stream and copied into the diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index e0b1c00..ab82531 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1372,7 +1372,7 @@ public class DevicePolicyManager { * * @hide */ - public boolean hasAnyCaCertsInstalled() { + public static boolean hasAnyCaCertsInstalled() { TrustedCertificateStore certStore = new TrustedCertificateStore(); Set<String> aliases = certStore.userAliases(); return aliases != null && !aliases.isEmpty(); 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.RemoteException; 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 @@ import java.util.UUID; * 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 @@ public final class BluetoothAdapter { } 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 @@ public final class BluetoothAdapter { 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 @@ import android.util.Log; * 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 @@ public class BluetoothMap { /** 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 @@ public class BluetoothMap { 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 @@ public class BluetoothMap { /** * 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 @@ public class BluetoothMap { 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 @@ public class BluetoothMap { } /** - * 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 @@ public class BluetoothMap { } /** - * 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 @@ public class BluetoothMap { } } + /** + * 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 @@ public class BluetoothMap { 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..abdf949 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -67,13 +67,16 @@ public final class BluetoothUuid { 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 final class BluetoothUuid { 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 @@ interface IBluetoothMap { 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/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java index dad60b0..b96c8d3 100644 --- a/core/java/android/content/ComponentCallbacks.java +++ b/core/java/android/content/ComponentCallbacks.java @@ -22,6 +22,11 @@ import android.content.res.Configuration; * The set of callback APIs that are common to all application components * ({@link android.app.Activity}, {@link android.app.Service}, * {@link ContentProvider}, and {@link android.app.Application}). + * + * <p class="note"><strong>Note:</strong> You should also implement the {@link + * ComponentCallbacks2} interface, which provides the {@link + * ComponentCallbacks2#onTrimMemory} callback to help your app manage its memory usage more + * effectively.</p> */ public interface ComponentCallbacks { /** @@ -29,26 +34,35 @@ public interface ComponentCallbacks { * component is running. Note that, unlike activities, other components * are never restarted when a configuration changes: they must always deal * with the results of the change, such as by re-retrieving resources. - * + * * <p>At the time that this function has been called, your Resources * object will have been updated to return resource values matching the * new configuration. - * + * + * <p>For more information, read <a href="{@docRoot}guide/topics/resources/runtime-changes.html" + * >Handling Runtime Changes</a>. + * * @param newConfig The new device configuration. */ void onConfigurationChanged(Configuration newConfig); - + /** * This is called when the overall system is running low on memory, and - * would like actively running process to try to tighten their belt. While + * actively running processes should trim their memory usage. While * the exact point at which this will be called is not defined, generally - * it will happen around the time all background process have been killed, - * that is before reaching the point of killing processes hosting + * it will happen when all background process have been killed. + * That is, before reaching the point of killing processes hosting * service and foreground UI that we would like to avoid killing. - * - * <p>Applications that want to be nice can implement this method to release - * any caches or other unnecessary resources they may be holding on to. - * The system will perform a gc for you after returning from this method. + * + * <p>You should implement this method to release + * any caches or other unnecessary resources you may be holding on to. + * The system will perform a garbage collection for you after returning from this method. + * <p>Preferably, you should implement {@link ComponentCallbacks2#onTrimMemory} from + * {@link ComponentCallbacks2} to incrementally unload your resources based on various + * levels of memory demands. That API is available for API level 14 and higher, so you should + * only use this {@link #onLowMemory} method as a fallback for older versions, which can be + * treated the same as {@link ComponentCallbacks2#onTrimMemory} with the {@link + * ComponentCallbacks2#TRIM_MEMORY_COMPLETE} level.</p> */ void onLowMemory(); } diff --git a/core/java/android/content/ComponentCallbacks2.java b/core/java/android/content/ComponentCallbacks2.java index a3b4e5e..b78548b 100644 --- a/core/java/android/content/ComponentCallbacks2.java +++ b/core/java/android/content/ComponentCallbacks2.java @@ -18,7 +18,68 @@ package android.content; /** * Extended {@link ComponentCallbacks} interface with a new callback for - * finer-grained memory management. + * finer-grained memory management. This interface is available in all application components + * ({@link android.app.Activity}, {@link android.app.Service}, + * {@link ContentProvider}, and {@link android.app.Application}). + * + * <p>You should implement {@link #onTrimMemory} to incrementally release memory based on current + * system constraints. Using this callback to release your resources helps provide a more + * responsive system overall, but also directly benefits the user experience for + * your app by allowing the system to keep your process alive longer. That is, + * if you <em>don't</em> trim your resources based on memory levels defined by this callback, + * the system is more likely to kill your process while it is cached in the least-recently used + * (LRU) list, thus requiring your app to restart and restore all state when the user returns to it. + * + * <p>The values provided by {@link #onTrimMemory} do not represent a single linear progression of + * memory limits, but provide you different types of clues about memory availability:</p> + * <ul> + * <li>When your app is running: + * <ol> + * <li>{@link #TRIM_MEMORY_RUNNING_MODERATE} <br>The device is beginning to run low on memory. + * Your app is running and not killable. + * <li>{@link #TRIM_MEMORY_RUNNING_LOW} <br>The device is running much lower on memory. + * Your app is running and not killable, but please release unused resources to improve system + * performance (which directly impacts your app's performance). + * <li>{@link #TRIM_MEMORY_RUNNING_CRITICAL} <br>The device is running extremely low on memory. + * Your app is not yet considered a killable process, but the system will begin killing + * background processes if apps do not release resources, so you should release non-critical + * resources now to prevent performance degradation. + * </ol> + * </li> + * <li>When your app's visibility changes: + * <ol> + * <li>{@link #TRIM_MEMORY_UI_HIDDEN} <br>Your app's UI is no longer visible, so this is a good + * time to release large resources that are used only by your UI. + * </ol> + * </li> + * <li>When your app's process resides in the background LRU list: + * <ol> + * <li>{@link #TRIM_MEMORY_BACKGROUND} <br>The system is running low on memory and your process is + * near the beginning of the LRU list. Although your app process is not at a high risk of being + * killed, the system may already be killing processes in the LRU list, so you should release + * resources that are easy to recover so your process will remain in the list and resume + * quickly when the user returns to your app. + * <li>{@link #TRIM_MEMORY_MODERATE} <br>The system is running low on memory and your process is + * near the middle of the LRU list. If the system becomes further constrained for memory, there's a + * chance your process will be killed. + * <li>{@link #TRIM_MEMORY_COMPLETE} <br>The system is running low on memory and your process is + * one of the first to be killed if the system does not recover memory now. You should release + * absolutely everything that's not critical to resuming your app state. + * <p>To support API levels lower than 14, you can use the {@link #onLowMemory} method as a + * fallback that's roughly equivalent to the {@link ComponentCallbacks2#TRIM_MEMORY_COMPLETE} level. + * </li> + * </ol> + * <p class="note"><strong>Note:</strong> When the system begins + * killing processes in the LRU list, although it primarily works bottom-up, it does give some + * consideration to which processes are consuming more memory and will thus provide more gains in + * memory if killed. So the less memory you consume while in the LRU list overall, the better + * your chances are to remain in the list and be able to quickly resume.</p> + * </li> + * </ul> + * <p>More information about the different stages of a process lifecycle (such as what it means + * to be placed in the background LRU list) is provided in the <a + * href="{@docRoot}guide/components/processes-and-threads.html#Lifecycle">Processes and Threads</a> + * document. */ public interface ComponentCallbacks2 extends ComponentCallbacks { diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 0a1d3f9..9a258dc 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -1573,8 +1573,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 { */ if (mContext == null) { mContext = context; - mTransport.mAppOpsManager = (AppOpsManager) mContext.getSystemService( - Context.APP_OPS_SERVICE); + if (context != null) { + mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService( + Context.APP_OPS_SERVICE); + } mMyUid = Process.myUid(); if (info != null) { setReadPermission(info.readPermission); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 92a9c7c..02ccaa5 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2132,13 +2132,8 @@ public abstract class Context { public static final String UPDATE_LOCK_SERVICE = "updatelock"; /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.net.NetworkManagementService} for handling management of - * system network services - * + * Constant for the internal network management service, not really a Context service. * @hide - * @see #getSystemService - * @see android.net.NetworkManagementService */ public static final String NETWORKMANAGEMENT_SERVICE = "network_management"; @@ -2327,7 +2322,7 @@ public abstract class Context { * android.hardware.SerialManager} for access to serial ports. * * @see #getSystemService - * @see android.harware.SerialManager + * @see android.hardware.SerialManager * * @hide */ @@ -2353,17 +2348,6 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a - * {@link android.os.SchedulingPolicyService} for managing scheduling policy. - * - * @see #getSystemService - * @see android.os.SchedulingPolicyService - * - * @hide - */ - public static final String SCHEDULING_POLICY_SERVICE = "scheduling_policy"; - - /** - * Use with {@link #getSystemService} to retrieve a * {@link android.os.UserManager} for managing users on devices that support multiple users. * * @see #getSystemService 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 @@ interface IPackageManager { 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..9203af9 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1196,6 +1196,13 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device supports device policy enforcement via device admins. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_DEVICE_ADMIN = "android.software.device_admin"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device supports WiFi (802.11) networking. */ @SdkConstant(SdkConstantType.FEATURE) @@ -3027,6 +3034,13 @@ public abstract class PackageManager { 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/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 4494e69..2e25177 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1441,18 +1441,29 @@ public class PackageParser { */ boolean required = true; // Optional <uses-permission> not supported + int maxSdkVersion = 0; + TypedValue val = sa.peekValue( + com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion); + if (val != null) { + if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) { + maxSdkVersion = val.data; + } + } + sa.recycle(); - if (name != null) { - int index = pkg.requestedPermissions.indexOf(name); - if (index == -1) { - pkg.requestedPermissions.add(name.intern()); - pkg.requestedPermissionsRequired.add(required ? Boolean.TRUE : Boolean.FALSE); - } else { - if (pkg.requestedPermissionsRequired.get(index) != required) { - outError[0] = "conflicting <uses-permission> entries"; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; + if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) { + if (name != null) { + int index = pkg.requestedPermissions.indexOf(name); + if (index == -1) { + pkg.requestedPermissions.add(name.intern()); + pkg.requestedPermissionsRequired.add(required ? Boolean.TRUE : Boolean.FALSE); + } else { + if (pkg.requestedPermissionsRequired.get(index) != required) { + outError[0] = "conflicting <uses-permission> entries"; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } } } } 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 interface CameraDevice extends AutoCloseable { 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 @@ public interface CameraDevice extends AutoCloseable { * 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/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index ec23f08..7f4ba4f 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -18,12 +18,25 @@ package android.hardware.camera2; import android.hardware.camera2.impl.CameraMetadataNative; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * The base class for camera controls and information. * + * <p> * This class defines the basic key/value map used for querying for camera * characteristics or capture results, and for setting camera request * parameters. + * </p> + * + * <p> + * All instances of CameraMetadata are immutable. The list of keys with {@link #getKeys()} + * never changes, nor do the values returned by any key with {@link #get} throughout + * the lifetime of the object. + * </p> * * @see CameraDevice * @see CameraManager @@ -38,9 +51,14 @@ public abstract class CameraMetadata { } /** - * Get a camera metadata field value. The field definitions can be + * Get a camera metadata field value. + * + * <p>The field definitions can be * found in {@link CameraProperties}, {@link CaptureResult}, and - * {@link CaptureRequest}. + * {@link CaptureRequest}.</p> + * + * <p>Querying the value for the same key more than once will return a value + * which is equal to the previous queried value.</p> * * @throws IllegalArgumentException if the key was not valid * @@ -49,6 +67,54 @@ public abstract class CameraMetadata { */ public abstract <T> T get(Key<T> key); + /** + * Returns a list of the keys contained in this map. + * + * <p>The list returned is not modifiable, so any attempts to modify it will throw + * a {@code UnsupportedOperationException}.</p> + * + * <p>All values retrieved by a key from this list with {@link #get} are guaranteed to be + * non-{@code null}. Each key is only listed once in the list. The order of the keys + * is undefined.</p> + * + * @return List of the keys contained in this map. + */ + public List<Key<?>> getKeys() { + return Collections.unmodifiableList(getKeysStatic(this.getClass(), this)); + } + + /** + * Return a list of all the Key<?> that are declared as a field inside of the class + * {@code type}. + * + * <p> + * Optionally, if {@code instance} is not null, then filter out any keys with null values. + * </p> + */ + /*package*/ static ArrayList<Key<?>> getKeysStatic(Class<? extends CameraMetadata> type, + CameraMetadata instance) { + ArrayList<Key<?>> keyList = new ArrayList<Key<?>>(); + + Field[] fields = type.getDeclaredFields(); + for (Field field : fields) { + if (field.getDeclaringClass().isAssignableFrom(Key.class)) { + Key<?> key; + try { + key = (Key<?>) field.get(instance); + } catch (IllegalAccessException e) { + throw new AssertionError("Can't get IllegalAccessException", e); + } catch (IllegalArgumentException e) { + throw new AssertionError("Can't get IllegalArgumentException", e); + } + if (instance == null || instance.get(key) != null) { + keyList.add(key); + } + } + } + + return keyList; + } + public static class Key<T> { private boolean mHasTag; diff --git a/core/java/android/hardware/camera2/CameraProperties.java b/core/java/android/hardware/camera2/CameraProperties.java index 45c009f..a2faf09 100644 --- a/core/java/android/hardware/camera2/CameraProperties.java +++ b/core/java/android/hardware/camera2/CameraProperties.java @@ -18,6 +18,9 @@ package android.hardware.camera2; import android.hardware.camera2.impl.CameraMetadataNative; +import java.util.Collections; +import java.util.List; + /** * <p>The properties describing a * {@link CameraDevice CameraDevice}.</p> @@ -32,6 +35,8 @@ import android.hardware.camera2.impl.CameraMetadataNative; public final class CameraProperties extends CameraMetadata { private final CameraMetadataNative mProperties; + private List<Key<?>> mAvailableRequestKeys; + private List<Key<?>> mAvailableResultKeys; /** * Takes ownership of the passed-in properties object @@ -46,6 +51,75 @@ public final class CameraProperties extends CameraMetadata { return mProperties.get(key); } + /** + * Returns the list of keys supported by this {@link CameraDevice} for querying + * with a {@link CaptureRequest}. + * + * <p>The list returned is not modifiable, so any attempts to modify it will throw + * a {@code UnsupportedOperationException}.</p> + * + * <p>Each key is only listed once in the list. The order of the keys is undefined.</p> + * + * <p>Note that there is no {@code getAvailableCameraPropertiesKeys()} -- use + * {@link #getKeys()} instead.</p> + * + * @return List of keys supported by this CameraDevice for CaptureRequests. + */ + public List<Key<?>> getAvailableCaptureRequestKeys() { + if (mAvailableRequestKeys == null) { + mAvailableRequestKeys = getAvailableKeyList(CaptureRequest.class); + } + return mAvailableRequestKeys; + } + + /** + * Returns the list of keys supported by this {@link CameraDevice} for querying + * with a {@link CaptureResult}. + * + * <p>The list returned is not modifiable, so any attempts to modify it will throw + * a {@code UnsupportedOperationException}.</p> + * + * <p>Each key is only listed once in the list. The order of the keys is undefined.</p> + * + * <p>Note that there is no {@code getAvailableCameraPropertiesKeys()} -- use + * {@link #getKeys()} instead.</p> + * + * @return List of keys supported by this CameraDevice for CaptureResults. + */ + public List<Key<?>> getAvailableCaptureResultKeys() { + if (mAvailableResultKeys == null) { + mAvailableResultKeys = getAvailableKeyList(CaptureResult.class); + } + return mAvailableResultKeys; + } + + /** + * Returns the list of keys supported by this {@link CameraDevice} by metadataClass. + * + * <p>The list returned is not modifiable, so any attempts to modify it will throw + * a {@code UnsupportedOperationException}.</p> + * + * <p>Each key is only listed once in the list. The order of the keys is undefined.</p> + * + * @param metadataClass The subclass of CameraMetadata that you want to get the keys for. + * + * @return List of keys supported by this CameraDevice for metadataClass. + * + * @throws IllegalArgumentException if metadataClass is not a subclass of CameraMetadata + */ + private <T extends CameraMetadata> List<Key<?>> getAvailableKeyList(Class<T> metadataClass) { + + if (metadataClass.equals(CameraMetadata.class)) { + throw new AssertionError( + "metadataClass must be a strict subclass of CameraMetadata"); + } else if (!CameraMetadata.class.isAssignableFrom(metadataClass)) { + throw new AssertionError( + "metadataClass must be a subclass of CameraMetadata"); + } + + return Collections.unmodifiableList(getKeysStatic(metadataClass, /*instance*/null)); + } + /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ * The key entries below this point are generated from metadata * definitions in /system/media/camera/docs. Do not modify by hand or @@ -341,6 +415,14 @@ public final class CameraProperties extends CameraMetadata { * platform opaque YUV/RGB streams to the GPU or video * encoders. Listed as width, height * </p> + * <p> + * The actual supported resolution list may be limited by + * consumer end points for different use cases. For example, for + * recording use case, the largest supported resolution may be + * limited by max supported size from encoder, for preview use + * case, the largest supported resolution may be limited by max + * resolution SurfaceTexture/SurfaceView can support. + * </p> */ public static final Key<android.hardware.camera2.Size[]> SCALER_AVAILABLE_PROCESSED_SIZES = new Key<android.hardware.camera2.Size[]>("android.scaler.availableProcessedSizes", android.hardware.camera2.Size[].class); diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 4608ab9..3ec5ca0 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -176,7 +176,7 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable { */ public final static class Builder { - private CaptureRequest mRequest; + private final CaptureRequest mRequest; /** * Initialize the builder using the template; the request takes diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 3fcd2f9..377e78a 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -51,89 +51,6 @@ public final class CaptureResult extends CameraMetadata { return mResults.get(key); } - /** - * Describes a face detected in an image. - */ - public static class Face { - - /** - * <p>Bounds of the face. A rectangle relative to the sensor's - * {@link CameraProperties#SENSOR_INFO_ACTIVE_ARRAY_SIZE}, with (0,0) - * representing the top-left corner of the active array rectangle.</p> - */ - public Rect getBounds() { - return mBounds; - } - - /** <p>The confidence level for the detection of the face. The range is 1 to - * 100. 100 is the highest confidence.</p> - * - * <p>Depending on the device, even very low-confidence faces may be - * listed, so applications should filter out faces with low confidence, - * depending on the use case. For a typical point-and-shoot camera - * application that wishes to display rectangles around detected faces, - * filtering out faces with confidence less than 50 is recommended.</p> - * - */ - public int getScore() { - return mScore; - } - - /** - * An unique id per face while the face is visible to the tracker. If - * the face leaves the field-of-view and comes back, it will get a new - * id. This is an optional field, may not be supported on all devices. - * If not supported, id will always be set to -1. The optional fields - * are supported as a set. Either they are all valid, or none of them - * are. - */ - public int getId() { - return mId; - } - - /** - * The coordinates of the center of the left eye. The coordinates are in - * the same space as the ones for {@link #getBounds}. This is an - * optional field, may not be supported on all devices. If not - * supported, the value will always be set to null. The optional fields - * are supported as a set. Either they are all valid, or none of them - * are. - */ - public Point getLeftEye() { - return mLeftEye; - } - - /** - * The coordinates of the center of the right eye. The coordinates are - * in the same space as the ones for {@link #getBounds}.This is an - * optional field, may not be supported on all devices. If not - * supported, the value will always be set to null. The optional fields - * are supported as a set. Either they are all valid, or none of them - * are. - */ - public Point getRightEye() { - return mRightEye; - } - - /** - * The coordinates of the center of the mouth. The coordinates are in - * the same space as the ones for {@link #getBounds}. This is an optional - * field, may not be supported on all devices. If not supported, the - * value will always be set to null. The optional fields are supported - * as a set. Either they are all valid, or none of them are. - */ - public Point getMouth() { - return mMouth; - } - - private Rect mBounds; - private int mScore; - private int mId; - private Point mLeftEye; - private Point mRightEye; - private Point mMouth; - } - /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ * The key entries below this point are generated from metadata * definitions in /system/media/camera/docs. Do not modify by hand or @@ -1003,4 +920,19 @@ public final class CaptureResult extends CameraMetadata { /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ * End generated code *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/ + + /** + * <p> + * List of the {@link Face Faces} detected through camera face detection + * in this result. + * </p> + * <p> + * Only available if {@link #STATISTICS_FACE_DETECT_MODE} {@code !=} + * {@link CameraMetadata#STATISTICS_FACE_DETECT_MODE_OFF OFF}. + * </p> + * + * @see Face + */ + public static final Key<Face[]> STATISTICS_FACES = + new Key<Face[]>("android.statistics.faces", Face[].class); } diff --git a/core/java/android/hardware/camera2/Face.java b/core/java/android/hardware/camera2/Face.java new file mode 100644 index 0000000..6bfc535 --- /dev/null +++ b/core/java/android/hardware/camera2/Face.java @@ -0,0 +1,252 @@ +/* + * 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 android.hardware.camera2; + +import android.graphics.Point; +import android.graphics.Rect; + +/** + * Describes a face detected in an image. + */ +public final class Face { + + /** + * The ID is {@code -1} when the optional set of fields is unsupported. + * + * @see Face#Face(Rect, int) + * @see #getId() + */ + public static final int ID_UNSUPPORTED = -1; + + /** + * The minimum possible value for the confidence level. + * + * @see #getScore() + */ + public static final int SCORE_MIN = 1; + + /** + * The maximum possible value for the confidence level. + * + * @see #getScore() + */ + public static final int SCORE_MAX = 100; + + private final Rect mBounds; + private final int mScore; + private final int mId; + private final Point mLeftEye; + private final Point mRightEye; + private final Point mMouth; + + /** + * Create a new face with all fields set. + * + * <p>The id, leftEyePosition, rightEyePosition, and mouthPosition are considered optional. + * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and + * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, + * rightEyePosition, and mouthPosition may be independently null or not-null.</p> + * + * @param bounds Bounds of the face. + * @param score Confidence level between {@value #SCORE_MIN}-{@value #SCORE_MAX}. + * @param id A unique ID per face visible to the tracker. + * @param leftEyePosition The position of the left eye. + * @param rightEyePosition The position of the right eye. + * @param mouthPosition The position of the mouth. + * + * @throws IllegalArgumentException + * if bounds is {@code null}, + * or if the confidence is not in the range of + * {@value #SCORE_MIN}-{@value #SCORE_MAX}, + * or if id is {@value #ID_UNSUPPORTED} and + * leftEyePosition/rightEyePosition/mouthPosition aren't all null, + * or else if id is negative. + * + * @hide + */ + public Face(Rect bounds, int score, int id, + Point leftEyePosition, Point rightEyePosition, Point mouthPosition) { + checkNotNull("bounds", bounds); + if (score < SCORE_MIN || score > SCORE_MAX) { + throw new IllegalArgumentException("Confidence out of range"); + } else if (id < 0 && id != ID_UNSUPPORTED) { + throw new IllegalArgumentException("Id out of range"); + } + if (id == ID_UNSUPPORTED) { + checkNull("leftEyePosition", leftEyePosition); + checkNull("rightEyePosition", rightEyePosition); + checkNull("mouthPosition", mouthPosition); + } + + mBounds = bounds; + mScore = score; + mId = id; + mLeftEye = leftEyePosition; + mRightEye = rightEyePosition; + mMouth = mouthPosition; + } + + /** + * Create a new face without the optional fields. + * + * <p>The id, leftEyePosition, rightEyePosition, and mouthPosition are considered optional. + * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and + * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, + * rightEyePosition, and mouthPosition may be independently null or not-null.</p> + * + * @param bounds Bounds of the face. + * @param score Confidence level between {@value #SCORE_MIN}-{@value #SCORE_MAX}. + * + * @throws IllegalArgumentException + * if bounds is {@code null}, + * or if the confidence is not in the range of + * {@value #SCORE_MIN}-{@value #SCORE_MAX}. + * + * @hide + */ + public Face(Rect bounds, int score) { + this(bounds, score, ID_UNSUPPORTED, + /*leftEyePosition*/null, /*rightEyePosition*/null, /*mouthPosition*/null); + } + + /** + * Bounds of the face. + * + * <p>A rectangle relative to the sensor's + * {@link CameraProperties#SENSOR_INFO_ACTIVE_ARRAY_SIZE}, with (0,0) + * representing the top-left corner of the active array rectangle.</p> + * + * <p>There is no constraints on the the Rectangle value other than it + * is not-{@code null}.</p> + */ + public Rect getBounds() { + return mBounds; + } + + /** + * The confidence level for the detection of the face. + * + * <p>The range is {@value #SCORE_MIN} to {@value #SCORE_MAX}. + * {@value #SCORE_MAX} is the highest confidence.</p> + * + * <p>Depending on the device, even very low-confidence faces may be + * listed, so applications should filter out faces with low confidence, + * depending on the use case. For a typical point-and-shoot camera + * application that wishes to display rectangles around detected faces, + * filtering out faces with confidence less than half of {@value #SCORE_MAX} + * is recommended.</p> + * + * @see #SCORE_MAX + * @see #SCORE_MIN + */ + public int getScore() { + return mScore; + } + + /** + * An unique id per face while the face is visible to the tracker. + * + * <p> + * If the face leaves the field-of-view and comes back, it will get a new + * id.</p> + * + * <p>This is an optional field, may not be supported on all devices. + * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and + * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, + * rightEyePosition, and mouthPosition may be independently null or not-null.</p> + * + * <p>This value will either be {@value #ID_UNSUPPORTED} or + * otherwise greater than {@code 0}.</p> + * + * @see #ID_UNSUPPORTED + */ + public int getId() { + return mId; + } + + /** + * The coordinates of the center of the left eye. + * + * <p>The coordinates are in + * the same space as the ones for {@link #getBounds}. This is an + * optional field, may not be supported on all devices. If not + * supported, the value will always be set to null. + * This value will always be null only if {@link #getId()} returns + * {@value #ID_UNSUPPORTED}.</p> + * + * @return The left eye position, or {@code null} if unknown. + */ + public Point getLeftEyePosition() { + return mLeftEye; + } + + /** + * The coordinates of the center of the right eye. + * + * <p>The coordinates are + * in the same space as the ones for {@link #getBounds}.This is an + * optional field, may not be supported on all devices. If not + * supported, the value will always be set to null. + * This value will always be null only if {@link #getId()} returns + * {@value #ID_UNSUPPORTED}.</p> + * + * @return The right eye position, or {@code null} if unknown. + */ + public Point getRightEyePosition() { + return mRightEye; + } + + /** + * The coordinates of the center of the mouth. + * + * <p>The coordinates are in + * the same space as the ones for {@link #getBounds}. This is an optional + * field, may not be supported on all devices. If not + * supported, the value will always be set to null. + * This value will always be null only if {@link #getId()} returns + * {@value #ID_UNSUPPORTED}.</p> them are. + * </p> + * + * @return The mouth position, or {@code null} if unknown. + */ + public Point getMouthPosition() { + return mMouth; + } + + /** + * Represent the Face as a string for debugging purposes. + */ + @Override + public String toString() { + return String.format("{ bounds: %s, score: %s, id: %d, " + + "leftEyePosition: %s, rightEyePosition: %s, mouthPosition: %s }", + mBounds, mScore, mId, mLeftEye, mRightEye, mMouth); + } + + private static void checkNotNull(String name, Object obj) { + if (obj == null) { + throw new IllegalArgumentException(name + " was required, but it was null"); + } + } + + private static void checkNull(String name, Object obj) { + if (obj != null) { + throw new IllegalArgumentException(name + " was required to be null, but it wasn't"); + } + } +} diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 020d7b6..c13438a 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -27,7 +27,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.HashMap; -import java.util.Map; /** * Implementation of camera metadata marshal/unmarshal across Binder to diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java index 2c05c58..d0b3ec4 100644 --- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java +++ b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java @@ -19,6 +19,7 @@ package android.hardware.camera2.utils; import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED; import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED; import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE; +import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE; import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL; import android.os.DeadObjectException; @@ -50,6 +51,7 @@ public class CameraBinderDecorator { public static final int EBUSY = -16; public static final int ENODEV = -19; public static final int EOPNOTSUPP = -95; + public static final int EDQUOT = -122; private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener { @@ -83,6 +85,9 @@ public class CameraBinderDecorator { case EBUSY: UncheckedThrow.throwAnyException(new CameraRuntimeException( CAMERA_IN_USE)); + case EDQUOT: + UncheckedThrow.throwAnyException(new CameraRuntimeException( + MAX_CAMERAS_IN_USE)); case ENODEV: UncheckedThrow.throwAnyException(new CameraRuntimeException( CAMERA_DISCONNECTED)); 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 @@ public class ProxyProperties implements Parcelable { 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 @@ public class ProxyProperties implements Parcelable { 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/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 2a18900..486e75a 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -227,9 +227,9 @@ public final class NfcAdapter { /** * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. * <p> - * Setting this flag enables polling for Kovio technology. + * Setting this flag enables polling for NfcBarcode technology. */ - public static final int FLAG_READER_KOVIO = 0x10; + public static final int FLAG_READER_NFC_BARCODE = 0x10; /** * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 8f68fc1..0c718f4 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -236,40 +236,40 @@ public final class Debug return dalvikSharedClean + nativeSharedClean + otherSharedClean; } - /* @hide */ + /** @hide */ public int getOtherPss(int which) { return otherStats[which*NUM_CATEGORIES + offsetPss]; } - /* @hide */ + /** @hide */ public int getOtherSwappablePss(int which) { return otherStats[which*NUM_CATEGORIES + offsetSwappablePss]; } - /* @hide */ + /** @hide */ public int getOtherPrivateDirty(int which) { return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty]; } - /* @hide */ + /** @hide */ public int getOtherSharedDirty(int which) { return otherStats[which*NUM_CATEGORIES + offsetSharedDirty]; } - /* @hide */ + /** @hide */ public int getOtherPrivateClean(int which) { return otherStats[which*NUM_CATEGORIES + offsetPrivateClean]; } - /* @hide */ + /** @hide */ public int getOtherSharedClean(int which) { return otherStats[which*NUM_CATEGORIES + offsetSharedClean]; } - /* @hide */ + /** @hide */ public static String getOtherLabel(int which) { switch (which) { case 0: return "Dalvik Other"; @@ -733,7 +733,7 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo /** * Clears the global size of objects allocated. - * @see #getGlobalAllocCountSize() + * @see #getGlobalAllocSize() */ public static void resetGlobalAllocSize() { VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); @@ -1018,6 +1018,28 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo */ 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 @@ public class Environment { * 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/os/Parcel.java b/core/java/android/os/Parcel.java index 46b0150..fec2a3e 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -228,6 +228,7 @@ public final class Parcel { private static final int EX_ILLEGAL_ARGUMENT = -3; private static final int EX_NULL_POINTER = -4; private static final int EX_ILLEGAL_STATE = -5; + private static final int EX_NETWORK_MAIN_THREAD = -6; private static final int EX_HAS_REPLY_HEADER = -128; // special; see below private static native int nativeDataSize(int nativePtr); @@ -1321,6 +1322,7 @@ public final class Parcel { * <li>{@link IllegalStateException} * <li>{@link NullPointerException} * <li>{@link SecurityException} + * <li>{@link NetworkOnMainThreadException} * </ul> * * @param e The Exception to be written. @@ -1340,6 +1342,8 @@ public final class Parcel { code = EX_NULL_POINTER; } else if (e instanceof IllegalStateException) { code = EX_ILLEGAL_STATE; + } else if (e instanceof NetworkOnMainThreadException) { + code = EX_NETWORK_MAIN_THREAD; } writeInt(code); StrictMode.clearGatheredViolations(); @@ -1455,6 +1459,8 @@ public final class Parcel { throw new NullPointerException(msg); case EX_ILLEGAL_STATE: throw new IllegalStateException(msg); + case EX_NETWORK_MAIN_THREAD: + throw new NetworkOnMainThreadException(); } throw new RuntimeException("Unknown exception code: " + code + " msg " + msg); diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java index b79bdee..30d535b 100644 --- a/core/java/android/os/WorkSource.java +++ b/core/java/android/os/WorkSource.java @@ -97,6 +97,16 @@ public class WorkSource implements Parcelable { } /** + * Clear names from this WorkSource. Uids are left intact. + * + * <p>Useful when combining with another WorkSource that doesn't have names. + * @hide + */ + public void clearNames() { + mNames = null; + } + + /** * Clear this WorkSource to be empty. */ public void clear() { diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl index fb6bb2e..4e839c6 100644 --- a/core/java/android/print/IPrintManager.aidl +++ b/core/java/android/print/IPrintManager.aidl @@ -19,9 +19,11 @@ package android.print; import android.print.IPrinterDiscoveryObserver; import android.print.IPrintDocumentAdapter; import android.print.IPrintClient; +import android.print.PrintJobId; import android.print.PrinterId; import android.print.PrintJobInfo; import android.print.PrintAttributes; +import android.printservice.PrintServiceInfo; /** * Interface for communication with the core print manager service. @@ -30,12 +32,14 @@ import android.print.PrintAttributes; */ interface IPrintManager { List<PrintJobInfo> getPrintJobInfos(int appId, int userId); - PrintJobInfo getPrintJobInfo(int printJobId, int appId, int userId); + PrintJobInfo getPrintJobInfo(in PrintJobId printJobId, int appId, int userId); PrintJobInfo print(String printJobName, in IPrintClient client, in IPrintDocumentAdapter printAdapter, in PrintAttributes attributes, int appId, int userId); - void cancelPrintJob(int printJobId, int appId, int userId); - void restartPrintJob(int printJobId, int appId, int userId); + void cancelPrintJob(in PrintJobId printJobId, int appId, int userId); + void restartPrintJob(in PrintJobId printJobId, int appId, int userId); + + List<PrintServiceInfo> getEnabledPrintServices(int userId); void createPrinterDiscoverySession(in IPrinterDiscoveryObserver observer, int userId); void startPrinterDiscovery(in IPrinterDiscoveryObserver observer, diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl index 0a77dab..291e81f 100644 --- a/core/java/android/print/IPrintSpooler.aidl +++ b/core/java/android/print/IPrintSpooler.aidl @@ -24,6 +24,8 @@ import android.print.IPrintSpoolerClient; import android.print.IPrintSpoolerCallbacks; import android.print.PrinterInfo; import android.print.PrintAttributes; +import android.print.PrintJobId; +import android.print.PrintJobInfo; /** * Interface for communication with the print spooler service. @@ -33,17 +35,18 @@ import android.print.PrintAttributes; * @hide */ oneway interface IPrintSpooler { + void removeObsoletePrintJobs(); + void forgetPrintJobs(in List<PrintJobId> printJob); void getPrintJobInfos(IPrintSpoolerCallbacks callback, in ComponentName componentName, int state, int appId, int sequence); - void getPrintJobInfo(int printJobId, IPrintSpoolerCallbacks callback, + void getPrintJobInfo(in PrintJobId printJobId, IPrintSpoolerCallbacks callback, int appId, int sequence); - void createPrintJob(String printJobName, in IPrintClient client, - in IPrintDocumentAdapter printAdapter, in PrintAttributes attributes, - IPrintSpoolerCallbacks callback, int appId, int sequence); - void setPrintJobState(int printJobId, int status, String error, + void createPrintJob(in PrintJobInfo printJob, in IPrintClient client, + in IPrintDocumentAdapter printAdapter); + void setPrintJobState(in PrintJobId printJobId, int status, String stateReason, IPrintSpoolerCallbacks callback, int sequence); - void setPrintJobTag(int printJobId, String tag, IPrintSpoolerCallbacks callback, + void setPrintJobTag(in PrintJobId printJobId, String tag, IPrintSpoolerCallbacks callback, int sequence); - void writePrintJobData(in ParcelFileDescriptor fd, int printJobId); + void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId); void setClient(IPrintSpoolerClient client); } diff --git a/core/java/android/print/IPrintSpoolerCallbacks.aidl b/core/java/android/print/IPrintSpoolerCallbacks.aidl index 51b5439..45c5332 100644 --- a/core/java/android/print/IPrintSpoolerCallbacks.aidl +++ b/core/java/android/print/IPrintSpoolerCallbacks.aidl @@ -28,7 +28,6 @@ import java.util.List; */ oneway interface IPrintSpoolerCallbacks { void onGetPrintJobInfosResult(in List<PrintJobInfo> printJob, int sequence); - void onCreatePrintJobResult(in PrintJobInfo printJob, int sequence); void onCancelPrintJobResult(boolean canceled, int sequence); void onSetPrintJobStateResult(boolean success, int sequence); void onSetPrintJobTagResult(boolean success, int sequence); diff --git a/core/java/android/print/IPrinterDiscoveryObserver.aidl b/core/java/android/print/IPrinterDiscoveryObserver.aidl index b558011..2be7b6b 100644 --- a/core/java/android/print/IPrinterDiscoveryObserver.aidl +++ b/core/java/android/print/IPrinterDiscoveryObserver.aidl @@ -18,6 +18,7 @@ package android.print; import android.print.PrinterId; import android.print.PrinterInfo; +import android.content.pm.ParceledListSlice; /** * Interface for observing discovered printers by a discovery session. @@ -25,6 +26,6 @@ import android.print.PrinterInfo; * @hide */ oneway interface IPrinterDiscoveryObserver { - void onPrintersAdded(in List<PrinterInfo> printers); - void onPrintersRemoved(in List<PrinterId> printerIds); + void onPrintersAdded(in ParceledListSlice printers); + void onPrintersRemoved(in ParceledListSlice printerIds); } diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java index d889353..efe6b15 100644 --- a/core/java/android/print/PrintAttributes.java +++ b/core/java/android/print/PrintAttributes.java @@ -373,27 +373,208 @@ public final class PrintAttributes implements Parcelable { // North America - /** North America Letter media size: 8.5" x 11" */ + /** North America Letter media size: 8.5" x 11" (279mm x 216mm) */ public static final MediaSize NA_LETTER = new MediaSize("NA_LETTER", "android", R.string.mediaSize_na_letter, 8500, 11000); - /** North America Government-Letter media size: 8.0" x 10.5" */ + /** North America Government-Letter media size: 8.0" x 10.5" (203mm x 267mm) */ public static final MediaSize NA_GOVT_LETTER = new MediaSize("NA_GOVT_LETTER", "android", R.string.mediaSize_na_gvrnmt_letter, 8000, 10500); - /** North America Legal media size: 8.5" x 14" */ + /** North America Legal media size: 8.5" x 14" (216mm x 356mm) */ public static final MediaSize NA_LEGAL = new MediaSize("NA_LEGAL", "android", R.string.mediaSize_na_legal, 8500, 14000); - /** North America Junior Legal media size: 8.0" x 5.0" */ + /** North America Junior Legal media size: 8.0" x 5.0" (203mm × 127mm) */ public static final MediaSize NA_JUNIOR_LEGAL = new MediaSize("NA_JUNIOR_LEGAL", "android", R.string.mediaSize_na_junior_legal, 8000, 5000); - /** North America Ledger media size: 17" x 11" */ + /** North America Ledger media size: 17" x 11" (432mm × 279mm) */ public static final MediaSize NA_LEDGER = new MediaSize("NA_LEDGER", "android", R.string.mediaSize_na_ledger, 17000, 11000); - /** North America Tabloid media size: 11" x 17" */ + /** North America Tabloid media size: 11" x 17" (279mm × 432mm) */ public static final MediaSize NA_TBLOID = new MediaSize("NA_TABLOID", "android", R.string.mediaSize_na_tabloid, 11000, 17000); + /** North America Index Card 3x5 media size: 3" x 5" (76mm x 127mm) */ + public static final MediaSize NA_INDEX_3X5 = + new MediaSize("NA_INDEX_3X5", "android", + R.string.mediaSize_na_index_3x5, 3000, 5000); + /** North America Index Card 4x6 media size: 4" x 6" (102mm x 152mm) */ + public static final MediaSize NA_INDEX_4X6 = + new MediaSize("NA_INDEX_4X6", "android", + R.string.mediaSize_na_index_4x6, 4000, 6000); + /** North America Index Card 5x8 media size: 5" x 8" (127mm x 203mm) */ + public static final MediaSize NA_INDEX_5X8 = + new MediaSize("NA_INDEX_5X8", "android", + R.string.mediaSize_na_index_5x8, 5000, 8000); + /** North America Monarch media size: 7.25" x 10.5" (184mm x 267mm) */ + public static final MediaSize NA_MONARCH = + new MediaSize("NA_MONARCH", "android", + R.string.mediaSize_na_monarch, 7250, 10500); + /** North America Quarto media size: 8" x 10" (203mm x 254mm) */ + public static final MediaSize NA_QUARTO = + new MediaSize("NA_QUARTO", "android", + R.string.mediaSize_na_quarto, 8000, 10000); + /** North America Foolscap media size: 8" x 13" (203mm x 330mm) */ + public static final MediaSize NA_FOOLSCAP = + new MediaSize("NA_FOOLSCAP", "android", + R.string.mediaSize_na_foolscap, 8000, 13000); + + // Chinese + + /** Chinese ROC 8K media size: 270mm x 390mm (10.629" x 15.3543") */ + public static final MediaSize ROC_8K = + new MediaSize("ROC_8K", "android", + R.string.mediaSize_chinese_roc_8k, 10629, 15354); + /** Chinese ROC 16K media size: 195mm x 270mm (7.677" x 10.629") */ + public static final MediaSize ROC_16K = + new MediaSize("ROC_16K", "android", + R.string.mediaSize_chinese_roc_16k, 7677, 10629); + + /** Chinese PRC 1 media size: 102mm x 165mm (4.015" x 6.496") */ + public static final MediaSize PRC_1 = + new MediaSize("PRC_1", "android", + R.string.mediaSize_chinese_prc_1, 4015, 6496); + /** Chinese PRC 2 media size: 102mm x 176mm (4.015" x 6.929") */ + public static final MediaSize PRC_2 = + new MediaSize("PRC_2", "android", + R.string.mediaSize_chinese_prc_2, 4015, 6929); + /** Chinese PRC 3 media size: 125mm x 176mm (4.921" x 6.929") */ + public static final MediaSize PRC_3 = + new MediaSize("PRC_3", "android", + R.string.mediaSize_chinese_prc_3, 4921, 6929); + /** Chinese PRC 4 media size: 110mm x 208mm (4.330" x 8.189") */ + public static final MediaSize PRC_4 = + new MediaSize("PRC_4", "android", + R.string.mediaSize_chinese_prc_4, 4330, 8189); + /** Chinese PRC 5 media size: 110mm x 220mm (4.330" x 8.661") */ + public static final MediaSize PRC_5 = + new MediaSize("PRC_5", "android", + R.string.mediaSize_chinese_prc_5, 4330, 8661); + /** Chinese PRC 6 media size: 120mm x 320mm (4.724" x 12.599") */ + public static final MediaSize PRC_6 = + new MediaSize("PRC_6", "android", + R.string.mediaSize_chinese_prc_6, 4724, 12599); + /** Chinese PRC 7 media size: 160mm x 230mm (6.299" x 9.055") */ + public static final MediaSize PRC_7 = + new MediaSize("PRC_7", "android", + R.string.mediaSize_chinese_prc_7, 6299, 9055); + /** Chinese PRC 8 media size: 120mm x 309mm (4.724" x 12.165") */ + public static final MediaSize PRC_8 = + new MediaSize("PRC_8", "android", + R.string.mediaSize_chinese_prc_8, 4724, 12165); + /** Chinese PRC 9 media size: 229mm x 324mm (9.016" x 12.756") */ + public static final MediaSize PRC_9 = + new MediaSize("PRC_9", "android", + R.string.mediaSize_chinese_prc_9, 9016, 12756); + /** Chinese PRC 10 media size: 324mm x 458mm (12.756" x 18.032") */ + public static final MediaSize PRC_10 = + new MediaSize("PRC_10", "android", + R.string.mediaSize_chinese_prc_10, 12756, 18032); + + /** Chinese PRC 16k media size: 146mm x 215mm (5.749" x 8.465") */ + public static final MediaSize PRC_16k = + new MediaSize("PRC_16k", "android", + R.string.mediaSize_chinese_prc_16k, 5749, 8465); + /** Chinese Pa Kai media size: 267mm x 389mm (10.512" x 15.315") */ + public static final MediaSize OM_PA_KAI = + new MediaSize("OM_PA_KAI", "android", + R.string.mediaSize_chinese_om_pa_kai, 10512, 15315); + /** Chinese Dai Pa Kai media size: 275mm x 395mm (10.827" x 15.551") */ + public static final MediaSize OM_DAI_PA_KAI = + new MediaSize("OM_DAI_PA_KAI", "android", + R.string.mediaSize_chinese_om_dai_pa_kai, 10827, 15551); + /** Chinese Jurro Ku Kai media size: 198mm x 275mm (7.796" x 10.827") */ + public static final MediaSize OM_JUURO_KU_KAI = + new MediaSize("OM_JUURO_KU_KAI", "android", + R.string.mediaSize_chinese_om_jurro_ku_kai, 7796, 10827); + + // Japanese + + /** Japanese JIS B10 media size: 32mm x 45mm (1.259" x 1.772") */ + public static final MediaSize JIS_B10 = + new MediaSize("JIS_B10", "android", + R.string.mediaSize_japanese_jis_b10, 1259, 1772); + /** Japanese JIS B9 media size: 45mm x 64mm (1.772" x 2.52") */ + public static final MediaSize JIS_B9 = + new MediaSize("JIS_B9", "android", + R.string.mediaSize_japanese_jis_b9, 1772, 2520); + /** Japanese JIS B8 media size: 64mm x 91mm (2.52" x 3.583") */ + public static final MediaSize JIS_B8 = + new MediaSize("JIS_B8", "android", + R.string.mediaSize_japanese_jis_b8, 2520, 3583); + /** Japanese JIS B7 media size: 91mm x 128mm (3.583" x 5.049") */ + public static final MediaSize JIS_B7 = + new MediaSize("JIS_B7", "android", + R.string.mediaSize_japanese_jis_b7, 3583, 5049); + /** Japanese JIS B6 media size: 128mm x 182mm (5.049" x 7.165") */ + public static final MediaSize JIS_B6 = + new MediaSize("JIS_B6", "android", + R.string.mediaSize_japanese_jis_b6, 5049, 7165); + /** Japanese JIS B5 media size: 182mm x 257mm (7.165" x 10.118") */ + public static final MediaSize JIS_B5 = + new MediaSize("JIS_B5", "android", + R.string.mediaSize_japanese_jis_b5, 7165, 10118); + /** Japanese JIS B4 media size: 257mm x 364mm (10.118" x 14.331") */ + public static final MediaSize JIS_B4 = + new MediaSize("JIS_B4", "android", + R.string.mediaSize_japanese_jis_b4, 10118, 14331); + /** Japanese JIS B3 media size: 364mm x 515mm (14.331" x 20.276") */ + public static final MediaSize JIS_B3 = + new MediaSize("JIS_B3", "android", + R.string.mediaSize_japanese_jis_b3, 14331, 20276); + /** Japanese JIS B2 media size: 515mm x 728mm (20.276" x 28.661") */ + public static final MediaSize JIS_B2 = + new MediaSize("JIS_B2", "android", + R.string.mediaSize_japanese_jis_b2, 20276, 28661); + /** Japanese JIS B1 media size: 728mm x 1030mm (28.661" x 40.551") */ + public static final MediaSize JIS_B1 = + new MediaSize("JIS_B1", "android", + R.string.mediaSize_japanese_jis_b1, 28661, 40551); + /** Japanese JIS B0 media size: 1030mm x 1456mm (40.551" x 57.323") */ + public static final MediaSize JIS_B0 = + new MediaSize("JIS_B0", "android", + R.string.mediaSize_japanese_jis_b0, 40551, 57323); + + /** Japanese JIS Exec media size: 216mm x 330mm (8.504" x 12.992") */ + public static final MediaSize JIS_EXEC = + new MediaSize("JIS_EXEC", "android", + R.string.mediaSize_japanese_jis_exec, 8504, 12992); + + /** Japanese Chou4 media size: 90mm x 205mm (3.543" x 8.071") */ + public static final MediaSize JPN_CHOU4 = + new MediaSize("JPN_CHOU4", "android", + R.string.mediaSize_japanese_chou4, 3543, 8071); + /** Japanese Chou3 media size: 120mm x 235mm (4.724" x 9.252") */ + public static final MediaSize JPN_CHOU3 = + new MediaSize("JPN_CHOU3", "android", + R.string.mediaSize_japanese_chou3, 4724, 9252); + /** Japanese Chou2 media size: 111.1mm x 146mm (4.374" x 5.748") */ + public static final MediaSize JPN_CHOU2 = + new MediaSize("JPN_CHOU2", "android", + R.string.mediaSize_japanese_chou2, 4374, 5748); + + /** Japanese Hagaki media size: 100mm x 148mm (3.937" x 5.827") */ + public static final MediaSize JPN_HAGAKI = + new MediaSize("JPN_HAGAKI", "android", + R.string.mediaSize_japanese_hagaki, 3937, 5827); + /** Japanese Oufuku media size: 148mm x 200mm (5.827" x 7.874") */ + public static final MediaSize JPN_OUFUKU = + new MediaSize("JPN_OUFUKU", "android", + R.string.mediaSize_japanese_oufuku, 5827, 7874); + + /** Japanese Kahu media size: 240mm x 322.1mm (9.449" x 12.681") */ + public static final MediaSize JPN_KAHU = + new MediaSize("JPN_KAHU", "android", + R.string.mediaSize_japanese_kahu, 9449, 12681); + /** Japanese Kaku2 media size: 240mm x 332mm (9.449" x 13.071") */ + public static final MediaSize JPN_KAKU2 = + new MediaSize("JPN_KAKU2", "android", + R.string.mediaSize_japanese_kaku2, 9449, 13071); + + /** Japanese You4 media size: 105mm x 235mm (4.134" x 9.252") */ + public static final MediaSize JPN_YOU4 = + new MediaSize("JPN_YOU4", "android", + R.string.mediaSize_japanese_you4, 4134, 9252); private final String mId; /**@hide */ diff --git a/core/java/android/print/PrintJob.java b/core/java/android/print/PrintJob.java index 42bea6d..00ade07 100644 --- a/core/java/android/print/PrintJob.java +++ b/core/java/android/print/PrintJob.java @@ -22,8 +22,6 @@ package android.print; */ public final class PrintJob { - private final int mId; - private final PrintManager mPrintManager; private PrintJobInfo mCachedInfo; @@ -31,7 +29,6 @@ public final class PrintJob { PrintJob(PrintJobInfo info, PrintManager printManager) { mCachedInfo = info; mPrintManager = printManager; - mId = info.getId(); } /** @@ -39,8 +36,8 @@ public final class PrintJob { * * @return The id. */ - public int getId() { - return mId; + public PrintJobId getId() { + return mCachedInfo.getId(); } /** @@ -57,7 +54,7 @@ public final class PrintJob { if (isInImmutableState()) { return mCachedInfo; } - PrintJobInfo info = mPrintManager.getPrintJobInfo(mId); + PrintJobInfo info = mPrintManager.getPrintJobInfo(mCachedInfo.getId()); if (info != null) { mCachedInfo = info; } @@ -69,7 +66,7 @@ public final class PrintJob { */ public void cancel() { if (!isInImmutableState()) { - mPrintManager.cancelPrintJob(mId); + mPrintManager.cancelPrintJob(mCachedInfo.getId()); } } @@ -91,11 +88,11 @@ public final class PrintJob { return false; } PrintJob other = (PrintJob) obj; - return mId == other.mId; + return mCachedInfo.getId().equals(other.mCachedInfo.getId()); } @Override public int hashCode() { - return mId; + return mCachedInfo.getId().hashCode(); } } diff --git a/core/java/android/print/PrintJobId.aidl b/core/java/android/print/PrintJobId.aidl new file mode 100644 index 0000000..759f25f --- /dev/null +++ b/core/java/android/print/PrintJobId.aidl @@ -0,0 +1,19 @@ +/** + * 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 android.print; + +parcelable PrintJobId; diff --git a/core/java/android/print/PrintJobId.java b/core/java/android/print/PrintJobId.java new file mode 100644 index 0000000..01550e2 --- /dev/null +++ b/core/java/android/print/PrintJobId.java @@ -0,0 +1,122 @@ +/* + * 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 android.print; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import java.util.UUID; + +/** + * This class represents the id of a print job. + */ +public final class PrintJobId implements Parcelable { + private final String mValue; + + /** + * Creates a new instance. + * + * @hide + */ + public PrintJobId() { + this(UUID.randomUUID().toString()); + } + + /** + * Creates a new instance. + * + * @param value The internal value. + * + * @hide + */ + public PrintJobId(String value) { + mValue = value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mValue != null) ? mValue.hashCode() : 0); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PrintJobId other = (PrintJobId) obj; + if (!TextUtils.equals(mValue, other.mValue)) { + return false; + } + return true; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(mValue); + } + + @Override + public int describeContents() { + return 0; + } + + /** + * Flattens this id to a string. + * + * @return The flattened id. + * + * @hide + */ + public String flattenToString() { + return mValue; + } + + /** + * Unflattens a print job id from a string. + * + * @string The string. + * @return The unflattened id, or null if the string is malformed. + * + * @hide + */ + public static PrintJobId unflattenFromString(String string) { + return new PrintJobId(string); + } + + public static final Parcelable.Creator<PrintJobId> CREATOR = + new Parcelable.Creator<PrintJobId>() { + @Override + public PrintJobId createFromParcel(Parcel parcel) { + return new PrintJobId(parcel.readString()); + } + + @Override + public PrintJobId[] newArray(int size) { + return new PrintJobId[size]; + } + }; +} diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java index b919ad6..502a9f2 100644 --- a/core/java/android/print/PrintJobInfo.java +++ b/core/java/android/print/PrintJobInfo.java @@ -56,8 +56,6 @@ public final class PrintJobInfo implements Parcelable { * <p> * Next valid states: {@link #STATE_QUEUED} * </p> - * - * @hide */ public static final int STATE_CREATED = 1; @@ -117,7 +115,7 @@ public final class PrintJobInfo implements Parcelable { public static final int STATE_CANCELED = 7; /** The unique print job id. */ - private int mId; + private PrintJobId mId; /** The human readable print job label. */ private String mLabel; @@ -178,7 +176,7 @@ public final class PrintJobInfo implements Parcelable { } private PrintJobInfo(Parcel parcel) { - mId = parcel.readInt(); + mId = parcel.readParcelable(null); mLabel = parcel.readString(); mPrinterId = parcel.readParcelable(null); mPrinterName = parcel.readString(); @@ -208,7 +206,7 @@ public final class PrintJobInfo implements Parcelable { * * @return The id. */ - public int getId() { + public PrintJobId getId() { return mId; } @@ -219,7 +217,7 @@ public final class PrintJobInfo implements Parcelable { * * @hide */ - public void setId(int id) { + public void setId(PrintJobId id) { this.mId = id; } @@ -485,7 +483,7 @@ public final class PrintJobInfo implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { - parcel.writeInt(mId); + parcel.writeParcelable(mId, flags); parcel.writeString(mLabel); parcel.writeParcelable(mPrinterId, flags); parcel.writeString(mPrinterName); diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index 6e32c05..5429155 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -28,6 +28,7 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.print.PrintDocumentAdapter.LayoutResultCallback; import android.print.PrintDocumentAdapter.WriteResultCallback; +import android.printservice.PrintServiceInfo; import android.text.TextUtils; import android.util.Log; @@ -35,7 +36,6 @@ import com.android.internal.os.SomeArgs; import libcore.io.IoUtils; -import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; @@ -113,7 +113,7 @@ public final class PrintManager { return new PrintManager(mContext, mService, userId, APP_ID_ANY); } - PrintJobInfo getPrintJobInfo(int printJobId) { + PrintJobInfo getPrintJobInfo(PrintJobId printJobId) { try { return mService.getPrintJobInfo(printJobId, mAppId, mUserId); } catch (RemoteException re) { @@ -147,7 +147,7 @@ public final class PrintManager { return Collections.emptyList(); } - void cancelPrintJob(int printJobId) { + void cancelPrintJob(PrintJobId printJobId) { try { mService.cancelPrintJob(printJobId, mAppId, mUserId); } catch (RemoteException re) { @@ -156,24 +156,6 @@ public final class PrintManager { } /** - * Creates a print job for printing a file with default print attributes. - * - * @param printJobName A name for the new print job. - * @param pdfFile The PDF file to print. - * @param documentInfo Information about the printed document. - * @param attributes The default print job attributes. - * @return The created print job on success or null on failure. - * - * @see PrintJob - */ - public PrintJob print(String printJobName, File pdfFile, PrintDocumentInfo documentInfo, - PrintAttributes attributes) { - PrintFileDocumentAdapter documentAdapter = new PrintFileDocumentAdapter( - mContext, pdfFile, documentInfo); - return print(printJobName, documentAdapter, attributes); - } - - /** * Creates a print job for printing a {@link PrintDocumentAdapter} with default print * attributes. * @@ -204,6 +186,25 @@ public final class PrintManager { } /** + * Gets the list of enabled print services. + * + * @return The enabled service list or an empty list. + * + * @hide + */ + public List<PrintServiceInfo> getEnabledPrintServices() { + try { + List<PrintServiceInfo> enabledServices = mService.getEnabledPrintServices(mUserId); + if (enabledServices != null) { + return enabledServices; + } + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error getting the enalbed print services", re); + } + return Collections.emptyList(); + } + + /** * @hide */ public PrinterDiscoverySession createPrinterDiscoverySession() { diff --git a/core/java/android/print/PrinterDiscoverySession.java b/core/java/android/print/PrinterDiscoverySession.java index 64249b4..c6dbc16 100644 --- a/core/java/android/print/PrinterDiscoverySession.java +++ b/core/java/android/print/PrinterDiscoverySession.java @@ -17,6 +17,7 @@ package android.print; import android.content.Context; +import android.content.pm.ParceledListSlice; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -270,20 +271,22 @@ public final class PrinterDiscoverySession { } @Override - public void onPrintersAdded(List<PrinterInfo> printers) { + @SuppressWarnings("rawtypes") + public void onPrintersAdded(ParceledListSlice printers) { PrinterDiscoverySession session = mWeakSession.get(); if (session != null) { session.mHandler.obtainMessage(MSG_PRINTERS_ADDED, - printers).sendToTarget(); + printers.getList()).sendToTarget(); } } @Override - public void onPrintersRemoved(List<PrinterId> printerIds) { + @SuppressWarnings("rawtypes") + public void onPrintersRemoved(ParceledListSlice printerIds) { PrinterDiscoverySession session = mWeakSession.get(); if (session != null) { session.mHandler.obtainMessage(MSG_PRINTERS_REMOVED, - printerIds).sendToTarget(); + printerIds.getList()).sendToTarget(); } } } diff --git a/core/java/android/printservice/IPrintServiceClient.aidl b/core/java/android/printservice/IPrintServiceClient.aidl index ad3c04f..c2dfc30 100644 --- a/core/java/android/printservice/IPrintServiceClient.aidl +++ b/core/java/android/printservice/IPrintServiceClient.aidl @@ -20,6 +20,8 @@ import android.os.ParcelFileDescriptor; import android.print.PrintJobInfo; import android.print.PrinterId; import android.print.PrinterInfo; +import android.print.PrintJobId; +import android.content.pm.ParceledListSlice; /** * The top-level interface from a print service to the system. @@ -28,11 +30,11 @@ import android.print.PrinterInfo; */ interface IPrintServiceClient { List<PrintJobInfo> getPrintJobInfos(); - PrintJobInfo getPrintJobInfo(int printJobId); - boolean setPrintJobState(int printJobId, int state, String error); - boolean setPrintJobTag(int printJobId, String tag); - oneway void writePrintJobData(in ParcelFileDescriptor fd, int printJobId); + PrintJobInfo getPrintJobInfo(in PrintJobId printJobId); + boolean setPrintJobState(in PrintJobId printJobId, int state, String error); + boolean setPrintJobTag(in PrintJobId printJobId, String tag); + oneway void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId); - void onPrintersAdded(in List<PrinterInfo> printers); - void onPrintersRemoved(in List<PrinterId> printerIds); + void onPrintersAdded(in ParceledListSlice printers); + void onPrintersRemoved(in ParceledListSlice printerIds); } diff --git a/core/java/android/printservice/PrintDocument.java b/core/java/android/printservice/PrintDocument.java index 8292cfb..e43f2a8 100644 --- a/core/java/android/printservice/PrintDocument.java +++ b/core/java/android/printservice/PrintDocument.java @@ -19,6 +19,7 @@ package android.printservice; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.print.PrintDocumentInfo; +import android.print.PrintJobId; import android.util.Log; import java.io.IOException; @@ -35,13 +36,13 @@ public final class PrintDocument { private static final String LOG_TAG = "PrintDocument"; - private final int mPrintJobId; + private final PrintJobId mPrintJobId; private final IPrintServiceClient mPrintServiceClient; private final PrintDocumentInfo mInfo; - PrintDocument(int printJobId, IPrintServiceClient printServiceClient, + PrintDocument(PrintJobId printJobId, IPrintServiceClient printServiceClient, PrintDocumentInfo info) { mPrintJobId = printJobId; mPrintServiceClient = printServiceClient; diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java index 4ff7f0c..2fcae6b 100644 --- a/core/java/android/printservice/PrintJob.java +++ b/core/java/android/printservice/PrintJob.java @@ -17,6 +17,7 @@ package android.printservice; import android.os.RemoteException; +import android.print.PrintJobId; import android.print.PrintJobInfo; import android.text.TextUtils; import android.util.Log; @@ -52,7 +53,7 @@ public final class PrintJob { * * @return The id. */ - public int getId() { + public PrintJobId getId() { PrintService.throwIfNotCalledOnMainThread(); return mCachedInfo.getId(); } @@ -312,12 +313,12 @@ public final class PrintJob { return false; } PrintJob other = (PrintJob) obj; - return (mCachedInfo.getId() == other.mCachedInfo.getId()); + return (mCachedInfo.getId().equals(other.mCachedInfo.getId())); } @Override public int hashCode() { - return mCachedInfo.getId(); + return mCachedInfo.getId().hashCode(); } private boolean isInImmutableState() { diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java index 012e76a..e5ebf77 100644 --- a/core/java/android/printservice/PrintService.java +++ b/core/java/android/printservice/PrintService.java @@ -178,6 +178,14 @@ public abstract class PrintService extends Service { * For detailed configuration options that can be specified via the meta-data * refer to {@link android.R.styleable#PrintService android.R.styleable.PrintService}. * </p> + * <p> + * If you declare a settings or add a printers activity, they have to be exported, + * by setting the {@link android.R.attr#exported} activity attribute to <code>true + * </code>. Also in case you want only the system to be able to start any of these + * activities you can specify that they request the android.permission + * .START_PRINT_SERVICE_CONFIG_ACTIVITY permission by setting the + * {@link android.R.attr#permission} activity attribute. + * </p> */ public static final String SERVICE_META_DATA = "android.printservice"; diff --git a/core/java/android/printservice/PrinterDiscoverySession.java b/core/java/android/printservice/PrinterDiscoverySession.java index b0bf3da..17cb68f 100644 --- a/core/java/android/printservice/PrinterDiscoverySession.java +++ b/core/java/android/printservice/PrinterDiscoverySession.java @@ -16,6 +16,7 @@ package android.printservice; +import android.content.pm.ParceledListSlice; import android.os.RemoteException; import android.print.PrinterCapabilitiesInfo; import android.print.PrinterId; @@ -80,8 +81,6 @@ import java.util.List; public abstract class PrinterDiscoverySession { private static final String LOG_TAG = "PrinterDiscoverySession"; - private static final int MAX_ITEMS_PER_CALLBACK = 50; - private static int sIdCounter = 0; private final int mId; @@ -112,7 +111,11 @@ public abstract class PrinterDiscoverySession { // If some printers were added in the method that // created the session, send them over. if (!mPrinters.isEmpty()) { - sendAddedPrinters(mObserver, getPrinters()); + try { + mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(getPrinters())); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error sending added printers", re); + } } } @@ -184,7 +187,11 @@ public abstract class PrinterDiscoverySession { // Send the added printers, if such. if (addedPrinters != null) { - sendAddedPrinters(mObserver, addedPrinters); + try { + mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(addedPrinters)); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error sending added printers", re); + } } } else { // Remember the last sent printers if needed. @@ -203,27 +210,6 @@ public abstract class PrinterDiscoverySession { } } - private static void sendAddedPrinters(IPrintServiceClient observer, - List<PrinterInfo> printers) { - try { - final int printerCount = printers.size(); - if (printerCount <= MAX_ITEMS_PER_CALLBACK) { - observer.onPrintersAdded(printers); - } else { - // Send the added printers in chunks avoiding the binder transaction limit. - final int transactionCount = (printerCount / MAX_ITEMS_PER_CALLBACK) + 1; - for (int i = 0; i < transactionCount; i++) { - final int start = i * MAX_ITEMS_PER_CALLBACK; - final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerCount); - List<PrinterInfo> subPrinters = printers.subList(start, end); - observer.onPrintersAdded(subPrinters); - } - } - } catch (RemoteException re) { - Log.e(LOG_TAG, "Error sending added printers", re); - } - } - /** * Removes added printers. Removing an already removed or never added * printer has no effect. Removed printers can be added again. You can @@ -261,7 +247,12 @@ public abstract class PrinterDiscoverySession { // Send the removed printers, if such. if (!removedPrinterIds.isEmpty()) { - sendRemovedPrinters(mObserver, removedPrinterIds); + try { + mObserver.onPrintersRemoved(new ParceledListSlice<PrinterId>( + removedPrinterIds)); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error sending removed printers", re); + } } } else { // Remember the last sent printers if needed. @@ -278,26 +269,6 @@ public abstract class PrinterDiscoverySession { } } - private static void sendRemovedPrinters(IPrintServiceClient observer, - List<PrinterId> printerIds) { - try { - final int printerIdCount = printerIds.size(); - if (printerIdCount <= MAX_ITEMS_PER_CALLBACK) { - observer.onPrintersRemoved(printerIds); - } else { - final int transactionCount = (printerIdCount / MAX_ITEMS_PER_CALLBACK) + 1; - for (int i = 0; i < transactionCount; i++) { - final int start = i * MAX_ITEMS_PER_CALLBACK; - final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerIdCount); - List<PrinterId> subPrinterIds = printerIds.subList(start, end); - observer.onPrintersRemoved(subPrinterIds); - } - } - } catch (RemoteException re) { - Log.e(LOG_TAG, "Error sending removed printers", re); - } - } - private void sendOutOfDiscoveryPeriodPrinterChanges() { // Noting changed since the last discovery period - nothing to do. if (mLastSentPrinters == null || mLastSentPrinters.isEmpty()) { @@ -319,7 +290,11 @@ public abstract class PrinterDiscoverySession { // Send the added printers, if such. if (addedPrinters != null) { - sendAddedPrinters(mObserver, addedPrinters); + try { + mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(addedPrinters)); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error sending added printers", re); + } } // Determine the removed printers. @@ -335,7 +310,11 @@ public abstract class PrinterDiscoverySession { // Send the removed printers, if such. if (removedPrinterIds != null) { - sendRemovedPrinters(mObserver, removedPrinterIds); + try { + mObserver.onPrintersRemoved(new ParceledListSlice<PrinterId>(removedPrinterIds)); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error sending removed printers", re); + } } mLastSentPrinters = null; 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 @@ public final class DocumentsContract { // 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 @@ public final class DocumentsContract { * @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 final class DocumentsContract { 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 @@ public final class DocumentsContract { * * @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 @@ public final class DocumentsContract { * * @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 @@ public final class DocumentsContract { * <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 @@ public final class DocumentsContract { * @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 @@ public final class DocumentsContract { } /** - * 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 @@ public final class DocumentsContract { /** * 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 @@ public abstract class DocumentsProvider extends ContentProvider { 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 @@ public abstract class DocumentsProvider extends ContentProvider { 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 @@ public abstract class DocumentsProvider extends ContentProvider { } /** - * 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 @@ public abstract class DocumentsProvider extends ContentProvider { 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 @@ public abstract class DocumentsProvider extends ContentProvider { } 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..6c6635d 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -160,6 +160,38 @@ public final class Settings { "android.settings.SECURITY_SETTINGS"; /** + * Activity Action: Show trusted credentials settings, opening to the user tab, + * to allow management of installed credentials. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_TRUSTED_CREDENTIALS_USER = + "com.android.settings.TRUSTED_CREDENTIALS_USER"; + + /** + * Activity Action: Show dialog explaining that an installed CA cert may enable + * monitoring of encrypted network traffic. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MONITORING_CERT_INFO = + "com.android.settings.MONITORING_CERT_INFO"; + + /** * Activity Action: Show settings to allow configuration of privacy options. * <p> * In some cases, a matching Activity may not exist, so ensure you @@ -4323,6 +4355,12 @@ public final class Settings { public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component"; /** + * Specifies the package name currently configured to be the primary sms application + * @hide + */ + public static final String SMS_DEFAULT_APPLICATION = "sms_default_application"; + + /** * Name of a package that the current user has explicitly allowed to see all of that * user's notifications. * @@ -4333,6 +4371,9 @@ public final class Settings { /** @hide */ public static final String BAR_SERVICE_COMPONENT = "bar_service_component"; + /** @hide */ + public static final String TRANSIENT_NAV_CONFIRMATIONS = "transient_nav_confirmations"; + /** * This are the settings to be backed up. * @@ -5642,6 +5683,9 @@ public final class Settings { /** {@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 +5712,13 @@ public final class Settings { } /** + * 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/android/transition/Fade.java b/core/java/android/transition/Fade.java index 12e0d73..5f948bd 100644 --- a/core/java/android/transition/Fade.java +++ b/core/java/android/transition/Fade.java @@ -41,7 +41,6 @@ public class Fade extends Visibility { private static boolean DBG = Transition.DBG && false; private static final String LOG_TAG = "Fade"; - private static final String PROPNAME_ALPHA = "android:fade:alpha"; private static final String PROPNAME_SCREEN_X = "android:fade:screenX"; private static final String PROPNAME_SCREEN_Y = "android:fade:screenY"; @@ -90,7 +89,11 @@ public class Fade extends Visibility { } return null; } - final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", startAlpha, endAlpha); + final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "transitionAlpha", startAlpha, + endAlpha); + if (DBG) { + Log.d(LOG_TAG, "Created animator " + anim); + } if (listener != null) { anim.addListener(listener); anim.addPauseListener(listener); @@ -99,8 +102,6 @@ public class Fade extends Visibility { } private void captureValues(TransitionValues transitionValues) { - float alpha = transitionValues.view.getAlpha(); - transitionValues.values.put(PROPNAME_ALPHA, alpha); int[] loc = new int[2]; transitionValues.view.getLocationOnScreen(loc); transitionValues.values.put(PROPNAME_SCREEN_X, loc[0]); @@ -113,29 +114,6 @@ public class Fade extends Visibility { captureValues(transitionValues); } - - @Override - public void captureEndValues(TransitionValues transitionValues) { - super.captureEndValues(transitionValues); - } - - @Override - public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, - TransitionValues endValues) { - Animator animator = super.createAnimator(sceneRoot, startValues, endValues); - if (animator == null && startValues != null && endValues != null) { - boolean endVisible = isVisible(endValues); - final View endView = endValues.view; - float endAlpha = endView.getAlpha(); - float startAlpha = (Float) startValues.values.get(PROPNAME_ALPHA); - if ((endVisible && startAlpha < endAlpha && (mFadingMode & Fade.IN) != 0) || - (!endVisible && startAlpha > endAlpha && (mFadingMode & Fade.OUT) != 0)) { - animator = createAnimation(endView, startAlpha, endAlpha, null); - } - } - return animator; - } - @Override public Animator onAppear(ViewGroup sceneRoot, TransitionValues startValues, int startVisibility, @@ -146,14 +124,40 @@ public class Fade extends Visibility { final View endView = endValues.view; if (DBG) { View startView = (startValues != null) ? startValues.view : null; - Log.d(LOG_TAG, "Fade.onDisappear: startView, startVis, endView, endVis = " + + Log.d(LOG_TAG, "Fade.onAppear: startView, startVis, endView, endVis = " + startView + ", " + startVisibility + ", " + endView + ", " + endVisibility); } - // if alpha < 1, just fade it in from the current value - if (endView.getAlpha() == 1.0f) { - endView.setAlpha(0); - } - return createAnimation(endView, endView.getAlpha(), 1, null); + endView.setTransitionAlpha(0); + TransitionListener transitionListener = new TransitionListenerAdapter() { + boolean mCanceled = false; + float mPausedAlpha; + + @Override + public void onTransitionCancel(Transition transition) { + endView.setTransitionAlpha(1); + mCanceled = true; + } + + @Override + public void onTransitionEnd(Transition transition) { + if (!mCanceled) { + endView.setTransitionAlpha(1); + } + } + + @Override + public void onTransitionPause(Transition transition) { + mPausedAlpha = endView.getTransitionAlpha(); + endView.setTransitionAlpha(1); + } + + @Override + public void onTransitionResume(Transition transition) { + endView.setTransitionAlpha(mPausedAlpha); + } + }; + addListener(transitionListener); + return createAnimation(endView, 0, 1, null); } @Override @@ -204,7 +208,7 @@ public class Fade extends Visibility { overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop()); sceneRoot.getOverlay().add(overlayView); // TODO: add automatic facility to Visibility superclass for keeping views around - final float startAlpha = view.getAlpha(); + final float startAlpha = 1; float endAlpha = 0; final View finalView = view; final View finalOverlayView = overlayView; @@ -213,7 +217,7 @@ public class Fade extends Visibility { final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - finalView.setAlpha(startAlpha); + finalView.setTransitionAlpha(startAlpha); // TODO: restore view offset from overlay repositioning if (finalViewToKeep != null) { finalViewToKeep.setVisibility(finalVisibility); @@ -244,7 +248,7 @@ public class Fade extends Visibility { // VISIBLE for the duration of the transition viewToKeep.setVisibility((View.VISIBLE)); // TODO: add automatic facility to Visibility superclass for keeping views around - final float startAlpha = view.getAlpha(); + final float startAlpha = 1; float endAlpha = 0; final View finalView = view; final View finalOverlayView = overlayView; @@ -259,8 +263,8 @@ public class Fade extends Visibility { if (finalViewToKeep != null && !mCanceled) { finalViewToKeep.setVisibility(finalVisibility); } - mPausedAlpha = finalView.getAlpha(); - finalView.setAlpha(startAlpha); + mPausedAlpha = finalView.getTransitionAlpha(); + finalView.setTransitionAlpha(startAlpha); } @Override @@ -268,21 +272,21 @@ public class Fade extends Visibility { if (finalViewToKeep != null && !mCanceled) { finalViewToKeep.setVisibility(View.VISIBLE); } - finalView.setAlpha(mPausedAlpha); + finalView.setTransitionAlpha(mPausedAlpha); } @Override public void onAnimationCancel(Animator animation) { mCanceled = true; if (mPausedAlpha >= 0) { - finalView.setAlpha(mPausedAlpha); + finalView.setTransitionAlpha(mPausedAlpha); } } @Override public void onAnimationEnd(Animator animation) { if (!mCanceled) { - finalView.setAlpha(startAlpha); + finalView.setTransitionAlpha(startAlpha); } // TODO: restore view offset from overlay repositioning if (finalViewToKeep != null && !mCanceled) { diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index c588c6b..4a99153 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -353,7 +353,7 @@ public abstract class Transition implements Cloneable { if (endValues.viewValues.get(view) != null) { end = endValues.viewValues.get(view); endCopy.remove(view); - } else { + } else if (id != View.NO_ID) { end = endValues.idValues.get(id); View removeView = null; for (View viewToRemove : endCopy.keySet()) { @@ -1240,12 +1240,13 @@ public abstract class Transition implements Cloneable { View oldView = oldInfo.view; TransitionValues newValues = mEndValues.viewValues != null ? mEndValues.viewValues.get(oldView) : null; + if (newValues == null) { + newValues = mEndValues.idValues.get(oldView.getId()); + } if (oldValues != null) { // if oldValues null, then transition didn't care to stash values, // and won't get canceled - if (newValues == null) { - cancel = true; - } else { + if (newValues != null) { for (String key : oldValues.values.keySet()) { Object oldValue = oldValues.values.get(key); Object newValue = newValues.values.get(key); @@ -1451,6 +1452,8 @@ public abstract class Transition implements Cloneable { try { clone = (Transition) super.clone(); clone.mAnimators = new ArrayList<Animator>(); + clone.mStartValues = new TransitionValuesMaps(); + clone.mEndValues = new TransitionValuesMaps(); } catch (CloneNotSupportedException e) {} return clone; diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java index 9904413..44ca4e5 100644 --- a/core/java/android/transition/TransitionManager.java +++ b/core/java/android/transition/TransitionManager.java @@ -22,6 +22,7 @@ import android.util.Log; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import java.lang.ref.WeakReference; import java.util.ArrayList; /** @@ -68,8 +69,9 @@ public class TransitionManager { ArrayMap<Scene, Transition> mSceneTransitions = new ArrayMap<Scene, Transition>(); ArrayMap<Scene, ArrayMap<Scene, Transition>> mScenePairTransitions = new ArrayMap<Scene, ArrayMap<Scene, Transition>>(); - private static ThreadLocal<ArrayMap<ViewGroup, ArrayList<Transition>>> sRunningTransitions = - new ThreadLocal<ArrayMap<ViewGroup, ArrayList<Transition>>>(); + private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>> + sRunningTransitions = + new ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>(); private static ArrayList<ViewGroup> sPendingTransitions = new ArrayList<ViewGroup>(); @@ -184,20 +186,24 @@ public class TransitionManager { } private static ArrayMap<ViewGroup, ArrayList<Transition>> getRunningTransitions() { - ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions = + WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>> runningTransitions = sRunningTransitions.get(); - if (runningTransitions == null) { - runningTransitions = new ArrayMap<ViewGroup, ArrayList<Transition>>(); + if (runningTransitions == null || runningTransitions.get() == null) { + ArrayMap<ViewGroup, ArrayList<Transition>> transitions = + new ArrayMap<ViewGroup, ArrayList<Transition>>(); + runningTransitions = new WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>( + transitions); sRunningTransitions.set(runningTransitions); } - return runningTransitions; + return runningTransitions.get(); } private static void sceneChangeRunTransition(final ViewGroup sceneRoot, final Transition transition) { if (transition != null) { final ViewTreeObserver observer = sceneRoot.getViewTreeObserver(); - observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + final ViewTreeObserver.OnPreDrawListener listener = + new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this); sPendingTransitions.remove(sceneRoot); @@ -236,7 +242,8 @@ public class TransitionManager { // values set on them again and avoid artifacts. return false; } - }); + }; + observer.addOnPreDrawListener(listener); } } @@ -351,10 +358,10 @@ public class TransitionManager { if (transition == null) { transition = sDefaultTransition; } - final Transition finalTransition = transition.clone(); - sceneChangeSetup(sceneRoot, transition); + final Transition transitionClone = transition.clone(); + sceneChangeSetup(sceneRoot, transitionClone); Scene.setCurrentScene(sceneRoot, null); - sceneChangeRunTransition(sceneRoot, finalTransition); + sceneChangeRunTransition(sceneRoot, transitionClone); } } } diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java index f72b36e..6fdd309 100644 --- a/core/java/android/transition/TransitionSet.java +++ b/core/java/android/transition/TransitionSet.java @@ -354,7 +354,7 @@ public class TransitionSet extends Transition { clone.mTransitions = new ArrayList<Transition>(); int numTransitions = mTransitions.size(); for (int i = 0; i < numTransitions; ++i) { - clone.mTransitions.add((Transition) mTransitions.get(i).clone()); + clone.addTransition((Transition) mTransitions.get(i).clone()); } return clone; } diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index 75d3e7c..f49821f 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -65,9 +65,6 @@ public abstract class Visibility extends Transition { ViewGroup endParent; } - // Temporary structure, used in calculating state in setup() and play() - private VisibilityInfo mTmpVisibilityInfo = new VisibilityInfo(); - @Override public String[] getTransitionProperties() { return sTransitionProperties; @@ -161,7 +158,7 @@ public abstract class Visibility extends Transition { private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues, TransitionValues endValues) { - final VisibilityInfo visInfo = mTmpVisibilityInfo; + final VisibilityInfo visInfo = new VisibilityInfo(); visInfo.visibilityChange = false; visInfo.fadeIn = false; if (startValues != null) { diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index a0d39ca..f36c78f 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -130,7 +130,7 @@ public class ScaleGestureDetector { private float mFocusX; private float mFocusY; - private boolean mDoubleTapScales; + private boolean mQuickScaleEnabled; private float mCurrSpan; private float mPrevSpan; @@ -307,7 +307,7 @@ public class ScaleGestureDetector { final int action = event.getActionMasked(); // Forward the event to check for double tap gesture - if (mDoubleTapScales) { + if (mQuickScaleEnabled) { mGestureDetector.onTouchEvent(event); } @@ -456,8 +456,8 @@ public class ScaleGestureDetector { * @param scales true to enable quick scaling, false to disable */ public void setQuickScaleEnabled(boolean scales) { - mDoubleTapScales = scales; - if (mDoubleTapScales && mGestureDetector == null) { + mQuickScaleEnabled = scales; + if (mQuickScaleEnabled && mGestureDetector == null) { GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() { @Override @@ -472,6 +472,14 @@ public class ScaleGestureDetector { } } + /** + * Return whether the quick scale gesture, in which the user performs a double tap followed by a + * swipe, should perform scaling. {@see #setQuickScaleEnabled(boolean)}. + */ + public boolean isQuickScaleEnabled() { + return mQuickScaleEnabled; + } + /** * Returns {@code true} if a scale gesture is in progress. */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a5db6ee..4680e76 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2894,6 +2894,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @ViewDebug.ExportedProperty float mAlpha = 1f; + + /** + * The opacity of the view as manipulated by the Fade transition. This is a hidden + * property only used by transitions, which is composited with the other alpha + * values to calculate the final visual alpha value. + */ + float mTransitionAlpha = 1f; } TransformationInfo mTransformationInfo; @@ -5335,7 +5342,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, View view = (View) current; // We have attach info so this view is attached and there is no // need to check whether we reach to ViewRootImpl on the way up. - if (view.getAlpha() <= 0 || view.getVisibility() != VISIBLE) { + if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 || + view.getVisibility() != VISIBLE) { return false; } current = view.mParent; @@ -9786,7 +9794,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags &= ~PFLAG_ALPHA_SET; invalidateViewProperty(true, false); if (mDisplayList != null) { - mDisplayList.setAlpha(alpha); + mDisplayList.setAlpha(getFinalAlpha()); } } } @@ -9813,7 +9821,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { mPrivateFlags &= ~PFLAG_ALPHA_SET; if (mDisplayList != null) { - mDisplayList.setAlpha(alpha); + mDisplayList.setAlpha(getFinalAlpha()); } } } @@ -9821,6 +9829,51 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * This property is hidden and intended only for use by the Fade transition, which + * animates it to produce a visual translucency that does not side-effect (or get + * affected by) the real alpha property. This value is composited with the other + * alpha value (and the AlphaAnimation value, when that is present) to produce + * a final visual translucency result, which is what is passed into the DisplayList. + * + * @hide + */ + public void setTransitionAlpha(float alpha) { + ensureTransformationInfo(); + if (mTransformationInfo.mTransitionAlpha != alpha) { + mTransformationInfo.mTransitionAlpha = alpha; + mPrivateFlags &= ~PFLAG_ALPHA_SET; + invalidateViewProperty(true, false); + if (mDisplayList != null) { + mDisplayList.setAlpha(getFinalAlpha()); + } + } + } + + /** + * Calculates the visual alpha of this view, which is a combination of the actual + * alpha value and the transitionAlpha value (if set). + */ + private float getFinalAlpha() { + if (mTransformationInfo != null) { + return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha; + } + return 1; + } + + /** + * This property is hidden and intended only for use by the Fade transition, which + * animates it to produce a visual translucency that does not side-effect (or get + * affected by) the real alpha property. This value is composited with the other + * alpha value (and the AlphaAnimation value, when that is present) to produce + * a final visual translucency result, which is what is passed into the DisplayList. + * + * @hide + */ + public float getTransitionAlpha() { + return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; + } + + /** * Top position of this view relative to its parent. * * @return The top of this view, in pixels. @@ -10913,7 +10966,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @ViewDebug.ExportedProperty(category = "drawing") public boolean isOpaque() { return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK && - ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f); + getFinalAlpha() >= 1.0f; } /** @@ -13868,7 +13921,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } if (mTransformationInfo != null) { - alpha *= mTransformationInfo.mAlpha; + alpha *= getFinalAlpha(); if (alpha < 1) { final int multipliedAlpha = (int) (255 * alpha); if (onSetAlpha(multipliedAlpha)) { @@ -14057,8 +14110,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } - float alpha = useDisplayListProperties ? 1 : getAlpha(); - if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() || + float alpha = useDisplayListProperties ? 1 : (getAlpha() * getTransitionAlpha()); + if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) { if (transformToApply != null || !childHasIdentityMatrix) { int transX = 0; @@ -14115,7 +14168,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; } if (useDisplayListProperties) { - displayList.setAlpha(alpha * getAlpha()); + displayList.setAlpha(alpha * getAlpha() * getTransitionAlpha()); } else if (layerType == LAYER_TYPE_NONE) { final int scrollX = hasDisplayList ? 0 : sx; final int scrollY = hasDisplayList ? 0 : sy; diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index 107d2c6..67a94be 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -702,7 +702,9 @@ public class ViewPropertyAnimator { @Override public void run() { mView.setLayerType(View.LAYER_TYPE_HARDWARE, null); - mView.buildLayer(); + if (mView.isAttachedToWindow()) { + mView.buildLayer(); + } } }; final int currentLayerType = mView.getLayerType(); diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index 730c4eb..f9298ea 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -990,6 +990,8 @@ public final class ViewTreeObserver { mStart = false; if (mDataCopy != null) { mData = mDataCopy; + mAccess.mData.clear(); + mAccess.mSize = 0; } mDataCopy = null; } diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java index de2be75..0957ab4 100644 --- a/core/java/android/widget/CalendarView.java +++ b/core/java/android/widget/CalendarView.java @@ -391,7 +391,7 @@ public class CalendarView extends FrameLayout { mWeekSeperatorLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, UNSCALED_WEEK_SEPARATOR_LINE_WIDTH, displayMetrics); - LayoutInflater layoutInflater = (LayoutInflater) mContext + LayoutInflater layoutInflater = (LayoutInflater) context .getSystemService(Service.LAYOUT_INFLATER_SERVICE); View content = layoutInflater.inflate(R.layout.calendar_view, null, false); addView(content); @@ -874,7 +874,6 @@ public class CalendarView extends FrameLayout { } mFirstDayOfWeek = firstDayOfWeek; mAdapter.init(); - mAdapter.notifyDataSetChanged(); setUpHeader(); } @@ -937,7 +936,7 @@ public class CalendarView extends FrameLayout { } private void updateDateTextSize() { - TypedArray dateTextAppearance = getContext().obtainStyledAttributes( + TypedArray dateTextAppearance = mContext.obtainStyledAttributes( mDateTextAppearanceResId, R.styleable.TextAppearance); mDateTextSize = dateTextAppearance.getDimensionPixelSize( R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE); @@ -1004,7 +1003,7 @@ public class CalendarView extends FrameLayout { */ private void setUpAdapter() { if (mAdapter == null) { - mAdapter = new WeeksAdapter(getContext()); + mAdapter = new WeeksAdapter(); mAdapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { @@ -1333,19 +1332,16 @@ public class CalendarView extends FrameLayout { * </p> */ private class WeeksAdapter extends BaseAdapter implements OnTouchListener { + private final Calendar mSelectedDate = Calendar.getInstance(); + private final GestureDetector mGestureDetector; private int mSelectedWeek; - private GestureDetector mGestureDetector; - private int mFocusedMonth; - private final Calendar mSelectedDate = Calendar.getInstance(); - private int mTotalWeekCount; - public WeeksAdapter(Context context) { - mContext = context; + public WeeksAdapter() { mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener()); init(); } @@ -1360,6 +1356,7 @@ public class CalendarView extends FrameLayout { || mMaxDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) { mTotalWeekCount++; } + notifyDataSetChanged(); } /** diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 19cc3c2..e4956dd 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -1099,6 +1099,16 @@ public class NumberPicker extends LinearLayout { } @Override + public int computeVerticalScrollOffset() { + return mCurrentScrollOffset; + } + + @Override + public int computeVerticalScrollRange() { + return mSelectorIndices.length * mSelectorElementHeight; + } + + @Override public int getSolidColor() { return mSolidColor; } diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 92c9b93..e03e83d 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -536,7 +536,7 @@ public class RelativeLayout extends ViewGroup { // the right of each child view width += mPaddingRight; - if (mLayoutParams.width >= 0) { + if (mLayoutParams != null && mLayoutParams.width >= 0) { width = Math.max(width, mLayoutParams.width); } @@ -566,7 +566,7 @@ public class RelativeLayout extends ViewGroup { // the bottom of each child view height += mPaddingBottom; - if (mLayoutParams.height >= 0) { + if (mLayoutParams != null && mLayoutParams.height >= 0) { height = Math.max(height, mLayoutParams.height); } |