summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl8
-rw-r--r--core/java/android/content/pm/PackageManager.java12
-rw-r--r--core/java/android/net/CaptivePortalTracker.java133
-rw-r--r--core/java/android/net/ConnectivityManager.java89
-rw-r--r--core/java/android/net/IConnectivityManager.aidl5
-rw-r--r--core/java/android/net/MobileDataStateTracker.java94
-rw-r--r--core/java/android/net/NetworkInfo.java7
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java20
-rw-r--r--core/java/android/nfc/cardemulation/CardEmulationManager.java101
-rw-r--r--core/java/android/nfc/cardemulation/HostApduService.java2
-rw-r--r--core/java/android/print/IPrintManager.aidl4
-rw-r--r--core/java/android/print/PrintDocumentAdapter.java18
-rw-r--r--core/java/android/print/PrintDocumentInfo.java30
-rw-r--r--core/java/android/print/PrintFileDocumentAdapter.java10
-rw-r--r--core/java/android/print/PrintJobInfo.java62
-rw-r--r--core/java/android/print/PrintManager.java13
-rw-r--r--core/java/android/print/PrinterDiscoverySession.java35
-rw-r--r--core/java/android/print/pdf/PrintedPdfDocument.java5
-rw-r--r--core/java/android/printservice/IPrintService.aidl4
-rw-r--r--core/java/android/printservice/PrintDocument.java11
-rw-r--r--core/java/android/printservice/PrintJob.java71
-rw-r--r--core/java/android/printservice/PrintService.java44
-rw-r--r--core/java/android/printservice/PrinterDiscoverySession.java100
-rw-r--r--core/java/android/provider/AlarmClock.java9
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--core/java/android/util/LayoutDirection.java8
-rw-r--r--core/java/android/webkit/WebView.java28
-rw-r--r--core/java/android/webkit/WebViewClassic.java7
-rw-r--r--core/java/android/webkit/WebViewProvider.java8
-rw-r--r--core/java/android/widget/GridLayout.java124
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java228
-rw-r--r--core/jni/android/graphics/Bitmap.cpp1
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp55
-rw-r--r--core/jni/android/graphics/BitmapRegionDecoder.cpp43
-rw-r--r--core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp276
-rw-r--r--core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h66
-rw-r--r--core/jni/android/graphics/Movie.cpp13
-rw-r--r--core/jni/android/graphics/Picture.cpp8
-rw-r--r--core/jni/android/graphics/Utils.cpp48
-rw-r--r--core/jni/android/graphics/Utils.h13
-rw-r--r--core/res/AndroidManifest.xml15
-rw-r--r--core/res/res/layout/resolve_list_item.xml48
-rw-r--r--core/res/res/layout/resolver_list.xml (renamed from core/res/res/layout/resolver_grid.xml)16
-rw-r--r--core/res/res/values-mcc208-mnc26/config.xml26
-rw-r--r--core/res/res/values-mcc214-mnc04/config.xml25
-rw-r--r--core/res/res/values-mcc234-mnc30/config.xml30
-rw-r--r--core/res/res/values-mcc234-mnc31/config.xml30
-rw-r--r--core/res/res/values-mcc234-mnc32/config.xml30
-rw-r--r--core/res/res/values-mcc234-mnc33/config.xml10
-rw-r--r--core/res/res/values-mcc234-mnc34/config.xml30
-rw-r--r--core/res/res/values-mcc234-mnc86/config.xml30
-rw-r--r--core/res/res/values-mcc302-mnc610/config.xml25
-rw-r--r--core/res/res/values-mcc302-mnc640/config.xml25
-rw-r--r--core/res/res/values-mcc302-mnc780/config.xml4
-rw-r--r--core/res/res/values-mcc425-mnc07/config.xml4
-rw-r--r--core/res/res/values-mcc425-mnc08/config.xml25
-rw-r--r--core/res/res/values/attrs.xml6
-rw-r--r--core/res/res/values/config.xml15
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--core/res/res/values/strings.xml16
-rw-r--r--[-rwxr-xr-x]core/res/res/values/symbols.xml8
61 files changed, 1589 insertions, 649 deletions
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index eba69b6..2b0c896 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -216,6 +216,12 @@ interface IPackageManager {
void resetPreferredActivities(int userId);
+ ResolveInfo getLastChosenActivity(in Intent intent,
+ String resolvedType, int flags);
+
+ void setLastChosenActivity(in Intent intent, String resolvedType, int flags,
+ in IntentFilter filter, int match, in ComponentName activity);
+
void addPreferredActivity(in IntentFilter filter, int match,
in ComponentName[] set, in ComponentName activity, int userId);
@@ -226,7 +232,7 @@ interface IPackageManager {
int getPreferredActivities(out List<IntentFilter> outFilters,
out List<ComponentName> outActivities, String packageName);
-
+
/**
* As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
*/
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 81f860e..d58b14c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -957,12 +957,24 @@ public abstract class PackageManager {
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports host-
* based NFC card emulation.
+ *
+ * TODO remove when depending apps have moved to new constant.
+ * @hide
+ * @deprecated
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_NFC_HCE = "android.hardware.nfc.hce";
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports host-
+ * based NFC card emulation.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes an accelerometer.
*/
@SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java
index 74c2c59..01977cd 100644
--- a/core/java/android/net/CaptivePortalTracker.java
+++ b/core/java/android/net/CaptivePortalTracker.java
@@ -16,22 +16,16 @@
package android.net;
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
-import android.os.UserHandle;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -46,7 +40,6 @@ import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -60,8 +53,6 @@ import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
-import com.android.internal.R;
-
/**
* This class allows captive portal detection on a network.
* @hide
@@ -71,7 +62,6 @@ public class CaptivePortalTracker extends StateMachine {
private static final String TAG = "CaptivePortalTracker";
private static final String DEFAULT_SERVER = "clients3.google.com";
- private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
private static final int SOCKET_TIMEOUT_MS = 10000;
@@ -93,7 +83,6 @@ public class CaptivePortalTracker extends StateMachine {
private String mServer;
private String mUrl;
- private boolean mNotificationShown = false;
private boolean mIsCaptivePortalCheckEnabled = false;
private IConnectivityManager mConnService;
private TelephonyManager mTelephonyManager;
@@ -192,12 +181,12 @@ public class CaptivePortalTracker extends StateMachine {
private class DefaultState extends State {
@Override
public void enter() {
- if (DBG) log(getName() + "\n");
+ setNotificationOff();
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_DETECT_PORTAL:
NetworkInfo info = (NetworkInfo) message.obj;
@@ -219,23 +208,24 @@ public class CaptivePortalTracker extends StateMachine {
private class NoActiveNetworkState extends State {
@Override
public void enter() {
- if (DBG) log(getName() + "\n");
mNetworkInfo = null;
- /* Clear any previous notification */
- setNotificationVisible(false);
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString());
InetAddress server;
NetworkInfo info;
switch (message.what) {
case CMD_CONNECTIVITY_CHANGE:
info = (NetworkInfo) message.obj;
- if (info.isConnected() && isActiveNetwork(info)) {
- mNetworkInfo = info;
- transitionTo(mDelayedCaptiveCheckState);
+ if (info.getType() == ConnectivityManager.TYPE_WIFI) {
+ if (info.isConnected() && isActiveNetwork(info)) {
+ mNetworkInfo = info;
+ transitionTo(mDelayedCaptiveCheckState);
+ }
+ } else {
+ log(getName() + " not a wifi connectivity change, ignore");
}
break;
default:
@@ -248,7 +238,7 @@ public class CaptivePortalTracker extends StateMachine {
private class ActiveNetworkState extends State {
@Override
public void enter() {
- if (DBG) log(getName() + "\n");
+ setNotificationOff();
}
@Override
@@ -281,7 +271,6 @@ public class CaptivePortalTracker extends StateMachine {
private class DelayedCaptiveCheckState extends State {
@Override
public void enter() {
- if (DBG) log(getName() + "\n");
Message message = obtainMessage(CMD_DELAYED_CAPTIVE_CHECK, ++mDelayedCheckToken, 0);
if (mDeviceProvisioned) {
sendMessageDelayed(message, DELAYED_CHECK_INTERVAL_MS);
@@ -292,7 +281,7 @@ public class CaptivePortalTracker extends StateMachine {
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_DELAYED_CAPTIVE_CHECK:
if (message.arg1 == mDelayedCheckToken) {
@@ -308,7 +297,12 @@ public class CaptivePortalTracker extends StateMachine {
if (captive) {
// Setup Wizard will assist the user in connecting to a captive
// portal, so make the notification visible unless during setup
- setNotificationVisible(true);
+ try {
+ mConnService.setProvisioningNotificationVisible(true,
+ mNetworkInfo.getType(), mNetworkInfo.getExtraInfo(), mUrl);
+ } catch(RemoteException e) {
+ e.printStackTrace();
+ }
}
} else {
Intent intent = new Intent(
@@ -366,6 +360,15 @@ public class CaptivePortalTracker extends StateMachine {
return false;
}
+ private void setNotificationOff() {
+ try {
+ mConnService.setProvisioningNotificationVisible(false, ConnectivityManager.TYPE_NONE,
+ null, null);
+ } catch (RemoteException e) {
+ log("setNotificationOff: " + e);
+ }
+ }
+
/**
* Do a URL fetch on a known server to see if we get the data we expect.
* Measure the response time and broadcast that.
@@ -394,17 +397,14 @@ public class CaptivePortalTracker extends StateMachine {
long responseTimestamp = SystemClock.elapsedRealtime();
// we got a valid response, but not from the real google
- boolean isCaptivePortal = urlConnection.getResponseCode() != 204;
+ int rspCode = urlConnection.getResponseCode();
+ boolean isCaptivePortal = rspCode != 204;
sendNetworkConditionsBroadcast(true /* response received */, isCaptivePortal,
requestTimestamp, responseTimestamp);
+
+ if (DBG) log("isCaptivePortal: ret=" + isCaptivePortal + " rspCode=" + rspCode);
return isCaptivePortal;
- } catch (SocketTimeoutException e) {
- if (DBG) log("Probably a portal: exception " + e);
- if (requestTimestamp != -1) {
- sendFailedCaptivePortalCheckBroadcast(requestTimestamp);
- } // else something went wrong with setting up the urlConnection
- return true;
} catch (IOException e) {
if (DBG) log("Probably not a portal: exception " + e);
if (requestTimestamp != -1) {
@@ -435,77 +435,6 @@ public class CaptivePortalTracker extends StateMachine {
return null;
}
- private void setNotificationVisible(boolean visible) {
- // if it should be hidden and it is already hidden, then noop
- if (!visible && !mNotificationShown) {
- if (DBG) log("setNotivicationVisible: false and not shown, so noop");
- return;
- }
-
- Resources r = Resources.getSystem();
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
-
- if (visible) {
- CharSequence title;
- CharSequence details;
- int icon;
- String url = null;
- switch (mNetworkInfo.getType()) {
- case ConnectivityManager.TYPE_WIFI:
- title = r.getString(R.string.wifi_available_sign_in, 0);
- details = r.getString(R.string.network_available_sign_in_detailed,
- mNetworkInfo.getExtraInfo());
- icon = R.drawable.stat_notify_wifi_in_range;
- url = mUrl;
- break;
- case ConnectivityManager.TYPE_MOBILE:
- title = r.getString(R.string.network_available_sign_in, 0);
- // TODO: Change this to pull from NetworkInfo once a printable
- // name has been added to it
- details = mTelephonyManager.getNetworkOperatorName();
- icon = R.drawable.stat_notify_rssi_in_range;
- try {
- url = mConnService.getMobileProvisioningUrl();
- if (TextUtils.isEmpty(url)) {
- url = mConnService.getMobileRedirectedProvisioningUrl();
- }
- } catch(RemoteException e) {
- e.printStackTrace();
- }
- if (TextUtils.isEmpty(url)) {
- url = mUrl;
- }
- break;
- default:
- title = r.getString(R.string.network_available_sign_in, 0);
- details = r.getString(R.string.network_available_sign_in_detailed,
- mNetworkInfo.getExtraInfo());
- icon = R.drawable.stat_notify_rssi_in_range;
- url = mUrl;
- break;
- }
-
- Notification notification = new Notification();
- notification.when = 0;
- notification.icon = icon;
- notification.flags = Notification.FLAG_AUTO_CANCEL;
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
- Intent.FLAG_ACTIVITY_NEW_TASK);
- notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
- notification.tickerText = title;
- notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
-
- if (DBG) log("setNotivicationVisible: make visible");
- notificationManager.notify(NOTIFICATION_ID, 1, notification);
- } else {
- if (DBG) log("setNotivicationVisible: cancel notification");
- notificationManager.cancel(NOTIFICATION_ID, 1);
- }
- mNotificationShown = visible;
- }
-
private void sendFailedCaptivePortalCheckBroadcast(long requestTimestampMs) {
sendNetworkConditionsBroadcast(false /* response received */, false /* ignored */,
requestTimestampMs, 0 /* ignored */);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index f6a3a4a..3874369 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -624,6 +624,29 @@ public class ConnectivityManager {
}
/**
+ * Returns details about the Provisioning or currently active default data network. When
+ * connected, this network is the default route for outgoing connections.
+ * You should always check {@link NetworkInfo#isConnected()} before initiating
+ * network traffic. This may return {@code null} when there is no default
+ * network.
+ *
+ * @return a {@link NetworkInfo} object for the current default network
+ * or {@code null} if no network default network is currently active
+ *
+ * <p>This method requires the call to hold the permission
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ *
+ * {@hide}
+ */
+ public NetworkInfo getProvisioningOrActiveNetworkInfo() {
+ try {
+ return mService.getProvisioningOrActiveNetworkInfo();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Returns the IP information for the current default network.
*
* @return a {@link LinkProperties} object describing the IP info
@@ -1357,63 +1380,19 @@ public class ConnectivityManager {
}
/**
- * The ResultReceiver resultCode for checkMobileProvisioning (CMP_RESULT_CODE)
- */
-
- /**
- * No connection was possible to the network.
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_NO_CONNECTION = 0;
-
- /**
- * A connection was made to the internet, all is well.
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_CONNECTABLE = 1;
-
- /**
- * A connection was made but there was a redirection, we appear to be in walled garden.
- * This is an indication of a warm sim on a mobile network.
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_REDIRECTED = 2;
-
- /**
- * A connection was made but no dns server was available to resolve a name to address.
- * This is an indication of a warm sim on a mobile network.
+ * Check mobile provisioning.
*
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_NO_DNS = 3;
-
- /**
- * A connection was made but could not open a TCP connection.
- * This is an indication of a warm sim on a mobile network.
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 4;
-
- /**
- * Check mobile provisioning. The resultCode passed to
- * onReceiveResult will be one of the CMP_RESULT_CODE_xxxx values above.
- * This may take a minute or more to complete.
- *
- * @param sendNotificaiton, when true a notification will be sent to user.
* @param suggestedTimeOutMs, timeout in milliseconds
- * @param resultReceiver needs to be supplied to receive the result
*
* @return time out that will be used, maybe less that suggestedTimeOutMs
* -1 if an error.
*
* {@hide}
*/
- public int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs,
- ResultReceiver resultReceiver) {
+ public int checkMobileProvisioning(int suggestedTimeOutMs) {
int timeOutMs = -1;
try {
- timeOutMs = mService.checkMobileProvisioning(sendNotification, suggestedTimeOutMs,
- resultReceiver);
+ timeOutMs = mService.checkMobileProvisioning(suggestedTimeOutMs);
} catch (RemoteException e) {
}
return timeOutMs;
@@ -1481,4 +1460,20 @@ public class ConnectivityManager {
return null;
}
}
+
+ /**
+ * Set sign in error notification to visible or in visible
+ *
+ * @param visible
+ * @param networkType
+ *
+ * {@hide}
+ */
+ public void setProvisioningNotificationVisible(boolean visible, int networkType,
+ String extraInfo, String url) {
+ try {
+ mService.setProvisioningNotificationVisible(visible, networkType, extraInfo, url);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index bf2dade..c07e900 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -50,6 +50,8 @@ interface IConnectivityManager
NetworkInfo getNetworkInfo(int networkType);
NetworkInfo[] getAllNetworkInfo();
+ NetworkInfo getProvisioningOrActiveNetworkInfo();
+
boolean isNetworkSupported(int networkType);
LinkProperties getActiveLinkProperties();
@@ -141,7 +143,7 @@ interface IConnectivityManager
int findConnectionTypeForIface(in String iface);
- int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, in ResultReceiver resultReceiver);
+ int checkMobileProvisioning(int suggestedTimeOutMs);
String getMobileProvisioningUrl();
@@ -153,4 +155,5 @@ interface IConnectivityManager
LinkInfo[] getAllLinkInfo();
+ void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo, in String url);
}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index faa13b0..125d5c1 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -61,8 +61,12 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
private ITelephony mPhoneService;
private String mApnType;
+ private NetworkInfo mNetworkInfo;
private boolean mTeardownRequested = false;
private Handler mTarget;
+ private Context mContext;
+ private LinkProperties mLinkProperties;
+ private LinkCapabilities mLinkCapabilities;
private boolean mPrivateDnsRouteSet = false;
private boolean mDefaultRouteSet = false;
@@ -106,6 +110,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
+ filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN);
filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
mContext.registerReceiver(new MobileDataStateReceiver(), filter);
@@ -184,10 +189,41 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
public void releaseWakeLock() {
}
+ private void updateLinkProperitesAndCapatilities(Intent intent) {
+ mLinkProperties = intent.getParcelableExtra(
+ PhoneConstants.DATA_LINK_PROPERTIES_KEY);
+ if (mLinkProperties == null) {
+ loge("CONNECTED event did not supply link properties.");
+ mLinkProperties = new LinkProperties();
+ }
+ mLinkCapabilities = intent.getParcelableExtra(
+ PhoneConstants.DATA_LINK_CAPABILITIES_KEY);
+ if (mLinkCapabilities == null) {
+ loge("CONNECTED event did not supply link capabilities.");
+ mLinkCapabilities = new LinkCapabilities();
+ }
+ }
+
private class MobileDataStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TelephonyIntents.
+ ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) {
+ String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
+ String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
+ if (!TextUtils.equals(mApnType, apnType)) {
+ return;
+ }
+ if (DBG) {
+ log("Broadcast received: " + intent.getAction() + " apnType=" + apnType
+ + " apnName=" + apnName);
+ }
+
+ // Make us in the connecting state until we make a new TYPE_MOBILE_PROVISIONING
+ mMobileDataState = PhoneConstants.DataState.CONNECTING;
+ updateLinkProperitesAndCapatilities(intent);
+ setDetailedState(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, "", apnName);
+ } else if (intent.getAction().equals(TelephonyIntents.
ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
if (VDBG) {
@@ -249,18 +285,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
setDetailedState(DetailedState.SUSPENDED, reason, apnName);
break;
case CONNECTED:
- mLinkProperties = intent.getParcelableExtra(
- PhoneConstants.DATA_LINK_PROPERTIES_KEY);
- if (mLinkProperties == null) {
- loge("CONNECTED event did not supply link properties.");
- mLinkProperties = new LinkProperties();
- }
- mLinkCapabilities = intent.getParcelableExtra(
- PhoneConstants.DATA_LINK_CAPABILITIES_KEY);
- if (mLinkCapabilities == null) {
- loge("CONNECTED event did not supply link capabilities.");
- mLinkCapabilities = new LinkCapabilities();
- }
+ updateLinkProperitesAndCapatilities(intent);
setDetailedState(DetailedState.CONNECTED, reason, apnName);
break;
}
@@ -319,8 +344,8 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY);
String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
if (DBG) {
- log("Received " + intent.getAction() +
- " broadcast" + (reason == null ? "" : "(" + reason + ")"));
+ log("Broadcast received: " + intent.getAction() +
+ " reason=" + reason == null ? "null" : reason);
}
setDetailedState(DetailedState.FAILED, reason, apnName);
} else {
@@ -412,6 +437,13 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED);
}
+ /**
+ * @return true if this is ready to operate
+ */
+ public boolean isReady() {
+ return mDataConnectionTrackerAc != null;
+ }
+
@Override
public void captivePortalCheckComplete() {
// not implemented
@@ -574,6 +606,40 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
}
}
+ /**
+ * Inform DCT mobile provisioning has started, it ends when provisioning completes.
+ */
+ public void enableMobileProvisioning(String url) {
+ if (DBG) log("enableMobileProvisioning(url=" + url + ")");
+ final AsyncChannel channel = mDataConnectionTrackerAc;
+ if (channel != null) {
+ Message msg = Message.obtain();
+ msg.what = DctConstants.CMD_ENABLE_MOBILE_PROVISIONING;
+ msg.setData(Bundle.forPair(DctConstants.PROVISIONING_URL_KEY, url));
+ channel.sendMessage(msg);
+ }
+ }
+
+ /**
+ * Return if this network is the provisioning network. Valid only if connected.
+ * @param met
+ */
+ public boolean isProvisioningNetwork() {
+ boolean retVal;
+ try {
+ Message msg = Message.obtain();
+ msg.what = DctConstants.CMD_IS_PROVISIONING_APN;
+ msg.setData(Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType));
+ Message result = mDataConnectionTrackerAc.sendMessageSynchronously(msg);
+ retVal = result.arg1 == DctConstants.ENABLED;
+ } catch (NullPointerException e) {
+ loge("isProvisioningNetwork: X " + e);
+ retVal = false;
+ }
+ if (DBG) log("isProvisioningNetwork: retVal=" + retVal);
+ return retVal;
+ }
+
@Override
public void addStackedLink(LinkProperties link) {
mLinkProperties.addStackedLink(link);
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 689dae5..dabc73a 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -84,6 +84,12 @@ public class NetworkInfo implements Parcelable {
VERIFYING_POOR_LINK,
/** Checking if network is a captive portal */
CAPTIVE_PORTAL_CHECK,
+ /**
+ * Network is connected to provisioning network
+ * TODO: Probably not needed when we add TYPE_PROVISIONING_NETWORK
+ * @hide
+ */
+ CONNECTED_TO_PROVISIONING_NETWORK
}
/**
@@ -108,6 +114,7 @@ public class NetworkInfo implements Parcelable {
stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED);
+ stateMap.put(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, State.CONNECTED);
}
private int mNetworkType;
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 3f7e3ef..b83911a 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -75,16 +75,22 @@ public final class ApduServiceInfo implements Parcelable {
final HashMap<String, AidGroup> mCategoryToGroup;
/**
+ * Whether this service should only be started when the device is unlocked.
+ */
+ final boolean mRequiresDeviceUnlock;
+
+ /**
* @hide
*/
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
- ArrayList<AidGroup> aidGroups) {
+ ArrayList<AidGroup> aidGroups, boolean requiresUnlock) {
this.mService = info;
this.mDescription = description;
this.mAidGroups = aidGroups;
this.mAids = new ArrayList<String>();
this.mCategoryToGroup = new HashMap<String, AidGroup>();
this.mOnHost = onHost;
+ this.mRequiresDeviceUnlock = requiresUnlock;
for (AidGroup aidGroup : aidGroups) {
this.mCategoryToGroup.put(aidGroup.category, aidGroup);
this.mAids.addAll(aidGroup.aids);
@@ -132,12 +138,16 @@ public final class ApduServiceInfo implements Parcelable {
mService = info;
mDescription = sa.getString(
com.android.internal.R.styleable.HostApduService_description);
+ mRequiresDeviceUnlock = sa.getBoolean(
+ com.android.internal.R.styleable.HostApduService_requireDeviceUnlock,
+ false);
} else {
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.OffHostApduService);
mService = info;
mDescription = sa.getString(
com.android.internal.R.styleable.OffHostApduService_description);
+ mRequiresDeviceUnlock = false;
}
mAidGroups = new ArrayList<AidGroup>();
@@ -226,6 +236,10 @@ public final class ApduServiceInfo implements Parcelable {
return mOnHost;
}
+ public boolean requiresUnlock() {
+ return mRequiresDeviceUnlock;
+ }
+
public CharSequence loadLabel(PackageManager pm) {
return mService.loadLabel(pm);
}
@@ -287,6 +301,7 @@ public final class ApduServiceInfo implements Parcelable {
if (mAidGroups.size() > 0) {
dest.writeTypedList(mAidGroups);
}
+ dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
};
public static final Parcelable.Creator<ApduServiceInfo> CREATOR =
@@ -301,7 +316,8 @@ public final class ApduServiceInfo implements Parcelable {
if (numGroups > 0) {
source.readTypedList(aidGroups, AidGroup.CREATOR);
}
- return new ApduServiceInfo(info, onHost, description, aidGroups);
+ boolean requiresUnlock = (source.readInt() != 0) ? true : false;
+ return new ApduServiceInfo(info, onHost, description, aidGroups, requiresUnlock);
}
@Override
diff --git a/core/java/android/nfc/cardemulation/CardEmulationManager.java b/core/java/android/nfc/cardemulation/CardEmulationManager.java
index 537fded..9d60c73 100644
--- a/core/java/android/nfc/cardemulation/CardEmulationManager.java
+++ b/core/java/android/nfc/cardemulation/CardEmulationManager.java
@@ -27,6 +27,7 @@ import android.nfc.INfcCardEmulation;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
import java.util.HashMap;
@@ -78,19 +79,68 @@ public final class CardEmulationManager {
*/
public static final String CATEGORY_OTHER = "other";
- static boolean sIsInitialized = false;
- static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap();
- static INfcCardEmulation sService;
+ /**
+ * Return value for {@link #getSelectionModeForCategory(String)}.
+ *
+ * <p>In this mode, the user has set a default service for this
+ * AID category. If a remote reader selects any of the AIDs
+ * that the default service has registered in this category,
+ * that service will automatically be bound to to handle
+ * the transaction.
+ *
+ * <p>There are still cases where a service that is
+ * not the default for a category can selected:
+ * <p>
+ * If a remote reader selects an AID in this category
+ * that is not handled by the default service, and there is a set
+ * of other services {S} that do handle this AID, the
+ * user is asked if he wants to use any of the services in
+ * {S} instead.
+ * <p>
+ * As a special case, if the size of {S} is one, containing a single service X,
+ * and all AIDs X has registered in this category are not
+ * registered by any other service, then X will be
+ * selected automatically without asking the user.
+ * <p>Example:
+ * <ul>
+ * <li>Service A registers AIDs "1", "2" and "3" in the category
+ * <li>Service B registers AIDs "3" and "4" in the category
+ * <li>Service C registers AIDs "5" and "6" in the category
+ * </ul>
+ * In this case, the following will happen when service A
+ * is the default:
+ * <ul>
+ * <li>Reader selects AID "1", "2" or "3": service A is invoked automatically
+ * <li>Reader selects AID "4": the user is asked to confirm he
+ * wants to use service B, because its AIDs overlap with service A.
+ * <li>Reader selects AID "5" or "6": service C is invoked automatically,
+ * because all AIDs it has asked for are only registered by C,
+ * and there is no overlap.
+ * </ul>
+ *
+ */
+ public static final int SELECTION_MODE_PREFER_DEFAULT = 0;
/**
- * @hide
+ * Return value for {@link #getSelectionModeForCategory(String)}.
+ *
+ * <p>In this mode, whenever an AID of this category is selected,
+ * the user is asked which service he wants to use to handle
+ * the transaction, even if there is only one matching service.
*/
- public static final String PAYMENT_MODE_AUTO = "auto";
+ public static final int SELECTION_MODE_ALWAYS_ASK = 1;
/**
- * @hide
+ * Return value for {@link #getSelectionModeForCategory(String)}.
+ *
+ * <p>In this mode, the user will only be asked to select a service
+ * if the selected AID has been registered by multiple applications.
*/
- public static final String PAYMENT_MODE_MANUAL = "manual";
+ public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2;
+
+ static boolean sIsInitialized = false;
+ static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap();
+ static INfcCardEmulation sService;
final Context mContext;
@@ -113,7 +163,7 @@ public final class CardEmulationManager {
throw new UnsupportedOperationException();
}
try {
- if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) {
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
Log.e(TAG, "This device does not support card emulation");
throw new UnsupportedOperationException();
}
@@ -137,6 +187,10 @@ public final class CardEmulationManager {
* Allows an application to query whether a service is currently
* the default service to handle a card emulation category.
*
+ * <p>Note that if {@link #getSelectionModeForCategory(String)}
+ * returns {@link #SELECTION_MODE_ALWAYS_ASK}, this method will always
+ * return false.
+ *
* @param service The ComponentName of the service
* @param category The category
* @return whether service is currently the default service for the category.
@@ -147,6 +201,10 @@ public final class CardEmulationManager {
} catch (RemoteException e) {
// Try one more time
recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
try {
return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service,
category);
@@ -186,6 +244,33 @@ public final class CardEmulationManager {
}
/**
+ * Returns the application selection mode for the passed in category.
+ * Valid return values are:
+ * <p>{@link #SELECTION_MODE_PREFER_DEFAULT} the user has requested a default
+ * application for this category, which will be preferred.
+ * <p>{@link #SELECTION_MODE_ALWAYS_ASK} the user has requested to be asked
+ * every time what app he would like to use in this category.
+ * <p>{@link #SELECTION_MODE_ASK_IF_CONFLICT} the user will only be asked
+ * to pick a service if there is a conflict.
+ * @param category The category, for example {@link #CATEGORY_PAYMENT}
+ * @return
+ */
+ public int getSelectionModeForCategory(String category) {
+ if (CATEGORY_PAYMENT.equals(category)) {
+ String defaultComponent = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
+ if (defaultComponent != null) {
+ return SELECTION_MODE_PREFER_DEFAULT;
+ } else {
+ return SELECTION_MODE_ALWAYS_ASK;
+ }
+ } else {
+ // All other categories are in "only ask if conflict" mode
+ return SELECTION_MODE_ASK_IF_CONFLICT;
+ }
+ }
+
+ /**
* @hide
*/
public boolean setDefaultServiceForCategory(ComponentName service, String category) {
diff --git a/core/java/android/nfc/cardemulation/HostApduService.java b/core/java/android/nfc/cardemulation/HostApduService.java
index cdc4adb..ae94b2f 100644
--- a/core/java/android/nfc/cardemulation/HostApduService.java
+++ b/core/java/android/nfc/cardemulation/HostApduService.java
@@ -4,13 +4,11 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Service;
import android.content.Intent;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
-import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl
index 3bfd9a1..fb6bb2e 100644
--- a/core/java/android/print/IPrintManager.aidl
+++ b/core/java/android/print/IPrintManager.aidl
@@ -41,7 +41,9 @@ interface IPrintManager {
void startPrinterDiscovery(in IPrinterDiscoveryObserver observer,
in List<PrinterId> priorityList, int userId);
void stopPrinterDiscovery(in IPrinterDiscoveryObserver observer, int userId);
- void requestPrinterUpdate(in PrinterId printerId, int userId);
+ void validatePrinters(in List<PrinterId> printerIds, int userId);
+ void startPrinterStateTracking(in PrinterId printerId, int userId);
+ void stopPrinterStateTracking(in PrinterId printerId, int userId);
void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer,
int userId);
}
diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java
index 8a64e85..33b4aad 100644
--- a/core/java/android/print/PrintDocumentAdapter.java
+++ b/core/java/android/print/PrintDocumentAdapter.java
@@ -18,8 +18,8 @@ package android.print;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
-import java.io.FileDescriptor;
import java.util.List;
/**
@@ -41,7 +41,7 @@ import java.util.List;
* <li>
* After every call to {@link #onLayout(PrintAttributes, PrintAttributes,
* CancellationSignal, LayoutResultCallback, Bundle)}, you may get a call to
- * {@link #onWrite(PageRange[], FileDescriptor, CancellationSignal, WriteResultCallback)}
+ * {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, WriteResultCallback)}
* asking you to write a PDF file with the content for specific pages.
* </li>
* <li>
@@ -64,7 +64,7 @@ import java.util.List;
* PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} on
* the UI thread (assuming onStart initializes resources needed for layout).
* This will ensure that the UI does not change while you are laying out the
- * printed content. Then you can handle {@link #onWrite(PageRange[], FileDescriptor,
+ * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor,
* CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another
* thread. This will ensure that the UI is frozen for the minimal amount of
* time. Also this assumes that you will generate the printed content in
@@ -150,10 +150,10 @@ public abstract class PrintDocumentAdapter {
* from of a PDF file to the given file descriptor. This method is invoked
* on the main thread.
*<p>
- * After you are done writing, you should <strong>not</strong> close the
- * file descriptor, rather you must invoke: {@link WriteResultCallback
- * #onWriteFinished(List)}, if writing completed successfully; or {@link
- * WriteResultCallback#onWriteFailed(CharSequence)}, if an error occurred.
+ * After you are done writing, you should close the file descriptor and
+ * invoke {@link WriteResultCallback #onWriteFinished(List)}, if writing
+ * completed successfully; or {@link WriteResultCallback#onWriteFailed(
+ * CharSequence)}, if an error occurred.
* </p>
* <p>
* <strong>Note:</strong> If the printed content is large, it is a good
@@ -171,7 +171,7 @@ public abstract class PrintDocumentAdapter {
* @see WriteResultCallback
* @see CancellationSignal
*/
- public abstract void onWrite(PageRange[] pages, FileDescriptor destination,
+ public abstract void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback);
/**
@@ -185,7 +185,7 @@ public abstract class PrintDocumentAdapter {
/**
* Base class for implementing a callback for the result of {@link
- * PrintDocumentAdapter#onWrite(PageRange[], FileDescriptor, CancellationSignal,
+ * PrintDocumentAdapter#onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
* WriteResultCallback)}.
*/
public static abstract class WriteResultCallback {
diff --git a/core/java/android/print/PrintDocumentInfo.java b/core/java/android/print/PrintDocumentInfo.java
index b32961b..f2b91ae 100644
--- a/core/java/android/print/PrintDocumentInfo.java
+++ b/core/java/android/print/PrintDocumentInfo.java
@@ -60,6 +60,7 @@ public final class PrintDocumentInfo implements Parcelable {
private int mColorMode;
private Margins mMargins;
private MediaSize mMediaSize;
+ private long mDataSize;
/**
* Creates a new instance.
@@ -82,6 +83,7 @@ public final class PrintDocumentInfo implements Parcelable {
mColorMode = prototype.mColorMode;
mMargins = prototype.mMargins;
mMediaSize = prototype.mMediaSize;
+ mDataSize = prototype.mDataSize;
}
/**
@@ -98,6 +100,7 @@ public final class PrintDocumentInfo implements Parcelable {
mColorMode = parcel.readInt();
mMargins = Margins.createFromParcel(parcel);
mMediaSize = MediaSize.createFromParcel(parcel);
+ mDataSize = parcel.readLong();
}
/**
@@ -188,6 +191,26 @@ public final class PrintDocumentInfo implements Parcelable {
return mMediaSize;
}
+ /**
+ * Gets the document data size in bytes.
+ *
+ * @return The data size.
+ */
+ public long getDataSize() {
+ return mDataSize;
+ }
+
+ /**
+ * Sets the document data size in bytes.
+ *
+ * @param dataSize The data size.
+ *
+ * @hide
+ */
+ public void setDataSize(long dataSize) {
+ mDataSize = dataSize;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -203,6 +226,7 @@ public final class PrintDocumentInfo implements Parcelable {
parcel.writeInt(mColorMode);
mMargins.writeToParcel(parcel);
mMediaSize.writeToParcel(parcel);
+ parcel.writeLong(mDataSize);
}
@Override
@@ -217,6 +241,8 @@ public final class PrintDocumentInfo implements Parcelable {
result = prime * result + mColorMode;
result = prime * result + (mMargins != null ? mMargins.hashCode() : 0);
result = prime * result + (mMediaSize != null ? mMediaSize.hashCode() : 0);
+ result = prime * result + (int) mDataSize;
+ result = prime * result + (int) mDataSize >> 32;
return result;
}
@@ -264,6 +290,9 @@ public final class PrintDocumentInfo implements Parcelable {
} else if (!mMediaSize.equals(other.mMediaSize)) {
return false;
}
+ if (mDataSize != other.mDataSize) {
+ return false;
+ }
return true;
}
@@ -279,6 +308,7 @@ public final class PrintDocumentInfo implements Parcelable {
builder.append(", colorMode=").append(PrintAttributes.colorModeToString(mColorMode));
builder.append(", margins=").append(mMargins);
builder.append(", mediaSize=").append(mMediaSize);
+ builder.append(", size=").append(mDataSize);
builder.append("}");
return builder.toString();
}
diff --git a/core/java/android/print/PrintFileDocumentAdapter.java b/core/java/android/print/PrintFileDocumentAdapter.java
index dbc8b6f..b905396 100644
--- a/core/java/android/print/PrintFileDocumentAdapter.java
+++ b/core/java/android/print/PrintFileDocumentAdapter.java
@@ -21,6 +21,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CancellationSignal.OnCancelListener;
+import android.os.ParcelFileDescriptor;
import android.util.Log;
import com.android.internal.R;
@@ -28,7 +29,6 @@ import com.android.internal.R;
import libcore.io.IoUtils;
import java.io.File;
-import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -81,7 +81,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
}
@Override
- public void onWrite(PageRange[] pages, FileDescriptor destination,
+ public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback) {
mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback);
mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
@@ -90,13 +90,13 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> {
- private final FileDescriptor mDestination;
+ private final ParcelFileDescriptor mDestination;
private final WriteResultCallback mResultCallback;
private final CancellationSignal mCancellationSignal;
- public WriteFileAsyncTask(FileDescriptor destination,
+ public WriteFileAsyncTask(ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback) {
mDestination = destination;
mResultCallback = callback;
@@ -112,7 +112,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
@Override
protected Void doInBackground(Void... params) {
InputStream in = null;
- OutputStream out = new FileOutputStream(mDestination);
+ OutputStream out = new FileOutputStream(mDestination.getFileDescriptor());
final byte[] buffer = new byte[8192];
try {
in = new FileInputStream(mFile);
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 602f3c1..b919ad6 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -44,6 +44,13 @@ public final class PrintJobInfo implements Parcelable {
public static final int STATE_ANY_VISIBLE_TO_CLIENTS = -2;
/**
+ * Constant for matching any active print job state.
+ *
+ * @hide
+ */
+ public static final int STATE_ANY_ACTIVE = -3;
+
+ /**
* Print job state: The print job is being created but not yet
* ready to be printed.
* <p>
@@ -55,7 +62,7 @@ public final class PrintJobInfo implements Parcelable {
public static final int STATE_CREATED = 1;
/**
- * Print job status: The print jobs is created, it is ready
+ * Print job state: The print jobs is created, it is ready
* to be printed and should be processed.
* <p>
* Next valid states: {@link #STATE_STARTED}, {@link #STATE_FAILED},
@@ -65,40 +72,49 @@ public final class PrintJobInfo implements Parcelable {
public static final int STATE_QUEUED = 2;
/**
- * Print job status: The print job is being printed.
+ * Print job state: The print job is being printed.
* <p>
* Next valid states: {@link #STATE_COMPLETED}, {@link #STATE_FAILED},
- * {@link #STATE_CANCELED}
+ * {@link #STATE_CANCELED}, {@link #STATE_BLOCKED}
* </p>
*/
public static final int STATE_STARTED = 3;
/**
- * Print job status: The print job was successfully printed.
+ * Print job state: The print job is blocked.
+ * <p>
+ * Next valid states: {@link #STATE_FAILED}, {@link #STATE_CANCELED},
+ * {@link #STATE_STARTED}
+ * </p>
+ */
+ public static final int STATE_BLOCKED = 4;
+
+ /**
+ * Print job state: The print job was successfully printed.
* This is a terminal state.
* <p>
* Next valid states: None
* </p>
*/
- public static final int STATE_COMPLETED = 4;
+ public static final int STATE_COMPLETED = 5;
/**
- * Print job status: The print job was printing but printing failed.
+ * Print job state: The print job was printing but printing failed.
* This is a terminal state.
* <p>
* Next valid states: None
* </p>
*/
- public static final int STATE_FAILED = 5;
+ public static final int STATE_FAILED = 6;
/**
- * Print job status: The print job was canceled.
+ * Print job state: The print job was canceled.
* This is a terminal state.
* <p>
* Next valid states: None
* </p>
*/
- public static final int STATE_CANCELED = 6;
+ public static final int STATE_CANCELED = 7;
/** The unique print job id. */
private int mId;
@@ -127,8 +143,8 @@ public final class PrintJobInfo implements Parcelable {
/** How many copies to print. */
private int mCopies;
- /** Failure reason if this job failed. */
- private String mFailureReason;
+ /** Reason for the print job being in its current state. */
+ private String mStateReason;
/** The pages to print */
private PageRange[] mPageRanges;
@@ -155,7 +171,7 @@ public final class PrintJobInfo implements Parcelable {
mUserId = other.mUserId;
mTag = other.mTag;
mCopies = other.mCopies;
- mFailureReason = other.mFailureReason;
+ mStateReason = other.mStateReason;
mPageRanges = other.mPageRanges;
mAttributes = other.mAttributes;
mDocumentInfo = other.mDocumentInfo;
@@ -171,7 +187,7 @@ public final class PrintJobInfo implements Parcelable {
mUserId = parcel.readInt();
mTag = parcel.readString();
mCopies = parcel.readInt();
- mFailureReason = parcel.readString();
+ mStateReason = parcel.readString();
if (parcel.readInt() == 1) {
Parcelable[] parcelables = parcel.readParcelableArray(null);
mPageRanges = new PageRange[parcelables.length];
@@ -377,25 +393,27 @@ public final class PrintJobInfo implements Parcelable {
}
/**
- * The failure reason if this print job failed.
+ * Gets the reason for the print job being in the current state.
*
- * @return The failure reason.
+ * @return The reason, or null if there is no reason or the
+ * reason is unknown.
*
* @hide
*/
- public String getFailureReason() {
- return mFailureReason;
+ public String getStateReason() {
+ return mStateReason;
}
/**
- * The failure reason if this print job failed.
+ * Sets the reason for the print job being in the current state.
*
- * @param failureReason The failure reason.
+ * @param stateReason The reason, or null if there is no reason
+ * or the reason is unknown.
*
* @hide
*/
- public void setFailureReason(String failureReason) {
- mFailureReason = failureReason;
+ public void setStateReason(String stateReason) {
+ mStateReason = stateReason;
}
/**
@@ -476,7 +494,7 @@ public final class PrintJobInfo implements Parcelable {
parcel.writeInt(mUserId);
parcel.writeString(mTag);
parcel.writeInt(mCopies);
- parcel.writeString(mFailureReason);
+ parcel.writeString(mStateReason);
if (mPageRanges != null) {
parcel.writeInt(1);
parcel.writeParcelableArray(mPageRanges, flags);
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index d3e35c3..6e32c05 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -36,7 +36,6 @@ import com.android.internal.os.SomeArgs;
import libcore.io.IoUtils;
import java.io.File;
-import java.io.FileDescriptor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
@@ -163,7 +162,7 @@ public final class PrintManager {
* @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.
+ * @return The created print job on success or null on failure.
*
* @see PrintJob
*/
@@ -181,7 +180,7 @@ public final class PrintManager {
* @param printJobName A name for the new print job.
* @param documentAdapter An adapter that emits the document to print.
* @param attributes The default print job attributes.
- * @return The created print job.
+ * @return The created print job on success or null on failure.
*
* @see PrintJob
*/
@@ -279,7 +278,7 @@ public final class PrintManager {
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = pages;
- args.arg2 = fd.getFileDescriptor();
+ args.arg2 = fd;
args.arg3 = callback;
args.argi1 = sequence;
mHandler.removeMessages(MyHandler.MSG_WRITE);
@@ -342,7 +341,7 @@ public final class PrintManager {
case MSG_WRITE: {
SomeArgs args = (SomeArgs) message.obj;
PageRange[] pages = (PageRange[]) args.arg1;
- FileDescriptor fd = (FileDescriptor) args.arg2;
+ ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg2;
IWriteResultCallback callback = (IWriteResultCallback) args.arg3;
final int sequence = args.argi1;
args.recycle();
@@ -428,12 +427,12 @@ public final class PrintManager {
}
private final class MyWriteResultCallback extends WriteResultCallback {
- private FileDescriptor mFd;
+ private ParcelFileDescriptor mFd;
private int mSequence;
private IWriteResultCallback mCallback;
public MyWriteResultCallback(IWriteResultCallback callback,
- FileDescriptor fd, int sequence) {
+ ParcelFileDescriptor fd, int sequence) {
mFd = fd;
mSequence = sequence;
mCallback = callback;
diff --git a/core/java/android/print/PrinterDiscoverySession.java b/core/java/android/print/PrinterDiscoverySession.java
index 8fbdd9c..46f0bef 100644
--- a/core/java/android/print/PrinterDiscoverySession.java
+++ b/core/java/android/print/PrinterDiscoverySession.java
@@ -74,6 +74,7 @@ public final class PrinterDiscoverySession {
public final void startPrinterDisovery(List<PrinterId> priorityList) {
if (isDestroyed()) {
Log.w(LOG_TAG, "Ignoring start printers dsicovery - session destroyed");
+ return;
}
if (!mIsPrinterDiscoveryStarted) {
mIsPrinterDiscoveryStarted = true;
@@ -88,6 +89,7 @@ public final class PrinterDiscoverySession {
public final void stopPrinterDiscovery() {
if (isDestroyed()) {
Log.w(LOG_TAG, "Ignoring stop printers discovery - session destroyed");
+ return;
}
if (mIsPrinterDiscoveryStarted) {
mIsPrinterDiscoveryStarted = false;
@@ -99,14 +101,39 @@ public final class PrinterDiscoverySession {
}
}
- public final void requestPrinterUpdate(PrinterId printerId) {
+ public final void startPrinterStateTracking(PrinterId printerId) {
+ if (isDestroyed()) {
+ Log.w(LOG_TAG, "Ignoring start printer state tracking - session destroyed");
+ return;
+ }
+ try {
+ mPrintManager.startPrinterStateTracking(printerId, mUserId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error starting printer state tracking", re);
+ }
+ }
+
+ public final void stopPrinterStateTracking(PrinterId printerId) {
if (isDestroyed()) {
- Log.w(LOG_TAG, "Ignoring reqeust printer update - session destroyed");
+ Log.w(LOG_TAG, "Ignoring stop printer state tracking - session destroyed");
+ return;
+ }
+ try {
+ mPrintManager.stopPrinterStateTracking(printerId, mUserId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error stoping printer state tracking", re);
+ }
+ }
+
+ public final void validatePrinters(List<PrinterId> printerIds) {
+ if (isDestroyed()) {
+ Log.w(LOG_TAG, "Ignoring validate printers - session destroyed");
+ return;
}
try {
- mPrintManager.requestPrinterUpdate(printerId, mUserId);
+ mPrintManager.validatePrinters(printerIds, mUserId);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error requesting printer update", re);
+ Log.e(LOG_TAG, "Error validating printers", re);
}
}
diff --git a/core/java/android/print/pdf/PrintedPdfDocument.java b/core/java/android/print/pdf/PrintedPdfDocument.java
index a3be38b..bee17ef 100644
--- a/core/java/android/print/pdf/PrintedPdfDocument.java
+++ b/core/java/android/print/pdf/PrintedPdfDocument.java
@@ -111,7 +111,10 @@ public final class PrintedPdfDocument {
* @see #finishPage(Page)
*/
public Page startPage(int pageNumber) {
- PageInfo pageInfo = new PageInfo.Builder(mPageSize, 0).create();
+ PageInfo pageInfo = new PageInfo
+ .Builder(mPageSize, 0)
+ .setContentSize(mContentSize)
+ .create();
Page page = mDocument.startPage(pageInfo);
return page;
}
diff --git a/core/java/android/printservice/IPrintService.aidl b/core/java/android/printservice/IPrintService.aidl
index 2cee1d8..ee36619 100644
--- a/core/java/android/printservice/IPrintService.aidl
+++ b/core/java/android/printservice/IPrintService.aidl
@@ -33,6 +33,8 @@ oneway interface IPrintService {
void createPrinterDiscoverySession();
void startPrinterDiscovery(in List<PrinterId> priorityList);
void stopPrinterDiscovery();
- void requestPrinterUpdate(in PrinterId printerId);
+ void validatePrinters(in List<PrinterId> printerIds);
+ void startPrinterStateTracking(in PrinterId printerId);
+ void stopPrinterStateTracking(in PrinterId printerId);
void destroyPrinterDiscoverySession();
}
diff --git a/core/java/android/printservice/PrintDocument.java b/core/java/android/printservice/PrintDocument.java
index 7437dc5..8292cfb 100644
--- a/core/java/android/printservice/PrintDocument.java
+++ b/core/java/android/printservice/PrintDocument.java
@@ -21,12 +21,15 @@ import android.os.RemoteException;
import android.print.PrintDocumentInfo;
import android.util.Log;
-import java.io.FileDescriptor;
import java.io.IOException;
/**
* This class represents a printed document from the perspective of a print
* service. It exposes APIs to query the document and obtain its data.
+ * <p>
+ * <strong>Note: </strong> All methods of this class must be executed on the
+ * main application thread.
+ * </p>
*/
public final class PrintDocument {
@@ -51,6 +54,7 @@ public final class PrintDocument {
* @return The document info.
*/
public PrintDocumentInfo getInfo() {
+ PrintService.throwIfNotCalledOnMainThread();
return mInfo;
}
@@ -64,7 +68,8 @@ public final class PrintDocument {
*
* @return A file descriptor for reading the data.
*/
- public FileDescriptor getData() {
+ public ParcelFileDescriptor getData() {
+ PrintService.throwIfNotCalledOnMainThread();
ParcelFileDescriptor source = null;
ParcelFileDescriptor sink = null;
try {
@@ -72,7 +77,7 @@ public final class PrintDocument {
source = fds[0];
sink = fds[1];
mPrintServiceClient.writePrintJobData(sink, mPrintJobId);
- return source.getFileDescriptor();
+ return source;
} catch (IOException ioe) {
Log.e(LOG_TAG, "Error calling getting print job data!", ioe);
} catch (RemoteException re) {
diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java
index d2fbef2..8bae9d6 100644
--- a/core/java/android/printservice/PrintJob.java
+++ b/core/java/android/printservice/PrintJob.java
@@ -18,6 +18,7 @@ package android.printservice;
import android.os.RemoteException;
import android.print.PrintJobInfo;
+import android.text.TextUtils;
import android.util.Log;
/**
@@ -123,6 +124,21 @@ public final class PrintJob {
}
/**
+ * Gets whether this print job is blocked. Such a print job is halted
+ * due to an abnormal condition and can be started or canceled or failed.
+ *
+ * @return Whether the print job is blocked.
+ *
+ * @see #start()
+ * @see #cancel()
+ * @see #fail(CharSequence)
+ */
+ public boolean isBlocked() {
+ PrintService.throwIfNotCalledOnMainThread();
+ return getInfo().getState() == PrintJobInfo.STATE_BLOCKED;
+ }
+
+ /**
* Gets whether this print job is completed. Such a print job
* is successfully printed. This is a final state.
*
@@ -163,21 +179,49 @@ public final class PrintJob {
/**
* Starts the print job. You should call this method if {@link
- * #isQueued()} returns true and you started printing.
+ * #isQueued()} or {@link #isBlocked()} returns true and you started
+ * resumed printing.
*
- * @return Whether the job as started.
+ * @return Whether the job was started.
*
* @see #isQueued()
+ * @see #isBlocked()
*/
public boolean start() {
PrintService.throwIfNotCalledOnMainThread();
- if (isQueued()) {
+ final int state = getInfo().getState();
+ if (state == PrintJobInfo.STATE_QUEUED
+ || state == PrintJobInfo.STATE_BLOCKED) {
return setState(PrintJobInfo.STATE_STARTED, null);
}
return false;
}
/**
+ * Blocks the print job. You should call this method if {@link
+ * #isStarted()} or {@link #isBlocked()} returns true and you need
+ * to block the print job. For example, the user has to add some
+ * paper to continue printing. To resume the print job call {@link
+ * #start()}.
+ *
+ * @return Whether the job was blocked.
+ *
+ * @see #isStarted()
+ * @see #isBlocked()
+ */
+ public boolean block(String reason) {
+ PrintService.throwIfNotCalledOnMainThread();
+ PrintJobInfo info = getInfo();
+ final int state = info.getState();
+ if (state == PrintJobInfo.STATE_STARTED
+ || (state == PrintJobInfo.STATE_BLOCKED
+ && !TextUtils.equals(info.getStateReason(), reason))) {
+ return setState(PrintJobInfo.STATE_BLOCKED, reason);
+ }
+ return false;
+ }
+
+ /**
* Completes the print job. You should call this method if {@link
* #isStarted()} returns true and you are done printing.
*
@@ -195,8 +239,8 @@ public final class PrintJob {
/**
* Fails the print job. You should call this method if {@link
- * #isQueued()} or {@link #isStarted()} returns true you failed
- * while printing.
+ * #isQueued()} or {@link #isStarted()} or {@link #isBlocked()}
+ * returns true you failed while printing.
*
* @param error The human readable, short, and translated reason
* for the failure.
@@ -204,10 +248,11 @@ public final class PrintJob {
*
* @see #isQueued()
* @see #isStarted()
+ * @see #isBlocked()
*/
public boolean fail(String error) {
PrintService.throwIfNotCalledOnMainThread();
- if (isQueued() || isStarted()) {
+ if (!isInImmutableState()) {
return setState(PrintJobInfo.STATE_FAILED, error);
}
return false;
@@ -215,18 +260,19 @@ public final class PrintJob {
/**
* Cancels the print job. You should call this method if {@link
- * #isQueued()} or {@link #isStarted()} returns true and you canceled
- * the print job as a response to a call to {@link
- * PrintService#onRequestCancelPrintJob(PrintJob)}.
+ * #isQueued()} or {@link #isStarted() or #isBlocked()} returns
+ * true and you canceled the print job as a response to a call to
+ * {@link PrintService#onRequestCancelPrintJob(PrintJob)}.
*
* @return Whether the job is canceled.
*
* @see #isStarted()
* @see #isQueued()
+ * @see #isBlocked()
*/
public boolean cancel() {
PrintService.throwIfNotCalledOnMainThread();
- if (isQueued() || isStarted()) {
+ if (!isInImmutableState()) {
return setState(PrintJobInfo.STATE_CANCELED, null);
}
return false;
@@ -277,7 +323,8 @@ public final class PrintJob {
private boolean isInImmutableState() {
final int state = mCachedInfo.getState();
return state == PrintJobInfo.STATE_COMPLETED
- || state == PrintJobInfo.STATE_CANCELED;
+ || state == PrintJobInfo.STATE_CANCELED
+ || state == PrintJobInfo.STATE_FAILED;
}
private boolean setState(int state, String error) {
@@ -287,7 +334,7 @@ public final class PrintJob {
// we may not be able to re-fetch it later if the job gets
// removed from the spooler as a result of the state change.
mCachedInfo.setState(state);
- mCachedInfo.setFailureReason(error);
+ mCachedInfo.setStateReason(error);
return true;
}
} catch (RemoteException re) {
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index f6c0a9a..96552af 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -314,8 +314,20 @@ public abstract class PrintService extends Service {
}
@Override
- public void requestPrinterUpdate(PrinterId printerId) {
- mHandler.obtainMessage(ServiceHandler.MSG_REQUEST_PRINTER_UPDATE,
+ public void validatePrinters(List<PrinterId> printerIds) {
+ mHandler.obtainMessage(ServiceHandler.MSG_VALIDATE_PRINTERS,
+ printerIds).sendToTarget();
+ }
+
+ @Override
+ public void startPrinterStateTracking(PrinterId printerId) {
+ mHandler.obtainMessage(ServiceHandler.MSG_START_PRINTER_STATE_TRACKING,
+ printerId).sendToTarget();
+ }
+
+ @Override
+ public void stopPrinterStateTracking(PrinterId printerId) {
+ mHandler.obtainMessage(ServiceHandler.MSG_STOP_PRINTER_STATE_TRACKING,
printerId).sendToTarget();
}
@@ -344,10 +356,12 @@ public abstract class PrintService extends Service {
public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
public static final int MSG_START_PRINTER_DISCOVERY = 3;
public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
- public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
- public static final int MSG_ON_PRINTJOB_QUEUED = 6;
- public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 7;
- public static final int MSG_SET_CLEINT = 8;
+ public static final int MSG_VALIDATE_PRINTERS = 5;
+ public static final int MSG_START_PRINTER_STATE_TRACKING = 6;
+ public static final int MSG_STOP_PRINTER_STATE_TRACKING = 7;
+ public static final int MSG_ON_PRINTJOB_QUEUED = 8;
+ public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 9;
+ public static final int MSG_SET_CLEINT = 10;
public ServiceHandler(Looper looper) {
super(looper, null, true);
@@ -391,10 +405,24 @@ public abstract class PrintService extends Service {
}
} break;
- case MSG_REQUEST_PRINTER_UPDATE: {
+ case MSG_VALIDATE_PRINTERS: {
+ if (mDiscoverySession != null) {
+ List<PrinterId> printerIds = (List<PrinterId>) message.obj;
+ mDiscoverySession.validatePrinters(printerIds);
+ }
+ } break;
+
+ case MSG_START_PRINTER_STATE_TRACKING: {
+ if (mDiscoverySession != null) {
+ PrinterId printerId = (PrinterId) message.obj;
+ mDiscoverySession.startPrinterStateTracking(printerId);
+ }
+ } break;
+
+ case MSG_STOP_PRINTER_STATE_TRACKING: {
if (mDiscoverySession != null) {
PrinterId printerId = (PrinterId) message.obj;
- mDiscoverySession.requestPrinterUpdate(printerId);
+ mDiscoverySession.stopPrinterStateTracking(printerId);
}
} break;
diff --git a/core/java/android/printservice/PrinterDiscoverySession.java b/core/java/android/printservice/PrinterDiscoverySession.java
index 8b959a6..1f86ecc 100644
--- a/core/java/android/printservice/PrinterDiscoverySession.java
+++ b/core/java/android/printservice/PrinterDiscoverySession.java
@@ -53,15 +53,23 @@ import java.util.List;
* session. Printers are <strong>not</strong> persisted across sessions.
* </p>
* <p>
- * The system will make a call to
- * {@link PrinterDiscoverySession#onRequestPrinterUpdate(PrinterId)} if you
- * need to update a given printer. It is possible that you add a printer without
+ * The system will make a call to {@link #onValidatePrinters(List)} if you
+ * need to update some printers. It is possible that you add a printer without
* specifying its capabilities. This enables you to avoid querying all discovered
* printers for their capabilities, rather querying the capabilities of a printer
* only if necessary. For example, the system will request that you update a printer
- * if it gets selected by the user. If you did not report the printer capabilities
- * when adding it, you must do so after the system requests a printer update.
- * Otherwise, the printer will be ignored.
+ * if it gets selected by the user. When validating printers you do not need to
+ * provide the printers' capabilities but may do so.
+ * </p>
+ * <p>
+ * If the system is interested in being constantly updated for the state of a
+ * printer you will receive a call to {@link #onStartPrinterStateTracking(PrinterId)}
+ * after which you will have to do a best effort to keep the system updated for
+ * changes in the printer state and capabilities. You also <strong>must</strong>
+ * update the printer capabilities if you did not provide them when adding it, or
+ * the printer will be ignored. When the system is no longer interested in getting
+ * updates for a printer you will receive a call to {@link #onStopPrinterStateTracking(
+ * PrinterId)}.
* </p>
* <p>
* <strong>Note: </strong> All callbacks in this class are executed on the main
@@ -115,7 +123,7 @@ public abstract class PrinterDiscoverySession {
* the printer that was added but not removed.
* <p>
* <strong>Note: </strong> Calls to this method after the session is
- * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+ * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
* </p>
*
* @return The printers.
@@ -139,7 +147,7 @@ public abstract class PrinterDiscoverySession {
* times during the life of this session. Duplicates will be ignored.
* <p>
* <strong>Note: </strong> Calls to this method after the session is
- * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+ * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
* </p>
*
* @param printers The printers to add.
@@ -218,7 +226,7 @@ public abstract class PrinterDiscoverySession {
* call this method multiple times during the lifetime of this session.
* <p>
* <strong>Note: </strong> Calls to this method after the session is
- * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+ * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
* </p>
*
* @param printerIds The ids of the removed printers.
@@ -293,7 +301,7 @@ public abstract class PrinterDiscoverySession {
* during the lifetime of this session.
* <p>
* <strong>Note: </strong> Calls to this method after the session is
- * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+ * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
* </p>
*
* @param printers The printers to update.
@@ -441,7 +449,9 @@ public abstract class PrinterDiscoverySession {
* <p>
* <strong>Note: </strong>You are also given a list of printers whose availability
* has to be checked first. For example, these printers could be the user's favorite
- * ones, therefore they have to be verified first.
+ * ones, therefore they have to be verified first. You do <strong>not need</strong>
+ * to provide the capabilities of the printers, rather verify whether they exist
+ * similarly to {@link #onValidatePrinters(List)}.
* </p>
*
* @param priorityList The list of printers to validate first. Never null.
@@ -463,9 +473,28 @@ public abstract class PrinterDiscoverySession {
public abstract void onStopPrinterDiscovery();
/**
- * Requests that you update a printer. You are responsible for updating
- * the printer by also reporting its capabilities via calling {@link
- * #updatePrinters(List)}.
+ * Callback asking you to validate that the given printers are valid, that
+ * is they exist. You are responsible for checking whether these printers
+ * exist and for the ones that do exist notify the system via calling
+ * {@link #updatePrinters(List)}.
+ * <p>
+ * <strong>Note: </strong> You are <strong>not required</strong> to provide
+ * the printer capabilities when updating the printers that do exist.
+ * <p>
+ *
+ * @param printerIds The printers to validate.
+ *
+ * @see #updatePrinters(List)
+ * @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo)
+ * PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo)
+ */
+ public abstract void onValidatePrinters(List<PrinterId> printerIds);
+
+ /**
+ * Callback asking you to start tracking the state of a printer. Tracking
+ * the state means that you should do a best effort to observe the state
+ * of this printer and notify the system if that state changes via calling
+ * {@link #updatePrinters(List)}.
* <p>
* <strong>Note: </strong> A printer can be initially added without its
* capabilities to avoid polling printers that the user will not select.
@@ -473,18 +502,33 @@ public abstract class PrinterDiscoverySession {
* printer <strong>including</strong> its capabilities. Otherwise, the
* printer will be ignored.
* <p>
- * A scenario when you may be requested to update a printer is if the user
- * selects it and the system has to present print options UI based on the
- * printer's capabilities.
+ * <p>
+ * A scenario when you may be requested to track a printer's state is if
+ * the user selects that printer and the system has to present print
+ * options UI based on the printer's capabilities. In this case the user
+ * should be promptly informed if, for example, the printer becomes
+ * unavailable.
* </p>
*
- * @param printerId The printer id.
+ * @param printerId The printer to start tracking.
*
+ * @see #onStopPrinterStateTracking(PrinterId)
* @see #updatePrinters(List)
* @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo)
* PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo)
*/
- public abstract void onRequestPrinterUpdate(PrinterId printerId);
+ public abstract void onStartPrinterStateTracking(PrinterId printerId);
+
+ /**
+ * Callback asking you to stop tracking the state of a printer. The passed
+ * in printer id is the one for which you received a call to {@link
+ * #onStartPrinterStateTracking(PrinterId)}.
+ *
+ * @param printerId The printer to stop tracking.
+ *
+ * @see #onStartPrinterStateTracking(PrinterId)
+ */
+ public abstract void onStopPrinterStateTracking(PrinterId printerId);
/**
* Notifies you that the session is destroyed. After this callback is invoked
@@ -538,9 +582,21 @@ public abstract class PrinterDiscoverySession {
}
}
- void requestPrinterUpdate(PrinterId printerId) {
- if (!mIsDestroyed) {
- onRequestPrinterUpdate(printerId);
+ void validatePrinters(List<PrinterId> printerIds) {
+ if (!mIsDestroyed && mObserver != null) {
+ onValidatePrinters(printerIds);
+ }
+ }
+
+ void startPrinterStateTracking(PrinterId printerId) {
+ if (!mIsDestroyed && mObserver != null) {
+ onStartPrinterStateTracking(printerId);
+ }
+ }
+
+ void stopPrinterStateTracking(PrinterId printerId) {
+ if (!mIsDestroyed && mObserver != null) {
+ onStopPrinterStateTracking(printerId);
}
}
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index 5e56e934..724d76d 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -90,6 +90,15 @@ public final class AlarmClock {
public static final String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
/**
+ * Activity Action: Show the alarms.
+ * <p>
+ * This action opens the alarms page.
+ * </p>
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+
+ /**
* Bundle extra: Weekdays for repeating alarm.
* <p>
* Used by {@link #ACTION_SET_ALARM}.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 24dbf0e..802bedf 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4285,12 +4285,6 @@ public final class Settings {
public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
/**
- * Whether to automatically invoke NFC payment app or manually select on tap.
- * @hide
- */
- public static final String NFC_PAYMENT_MODE = "nfc_payment_mode";
-
- /**
* Name of a package that the current user has explicitly allowed to see all of that
* user's notifications.
*
diff --git a/core/java/android/util/LayoutDirection.java b/core/java/android/util/LayoutDirection.java
index e37d2f2..20af20b 100644
--- a/core/java/android/util/LayoutDirection.java
+++ b/core/java/android/util/LayoutDirection.java
@@ -17,11 +17,15 @@
package android.util;
/**
- * An interface for defining layout directions. A layout direction can be left-to-right (LTR)
+ * A class for defining layout directions. A layout direction can be left-to-right (LTR)
* or right-to-left (RTL). It can also be inherited (from a parent) or deduced from the default
* language script of a locale.
*/
-public interface LayoutDirection {
+public final class LayoutDirection {
+
+ // No instantiation
+ private LayoutDirection() {}
+
/**
* Horizontal layout direction is from Left to Right.
*/
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1b57d50..eded438 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -31,7 +31,9 @@ import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.StrictMode;
+import android.print.PrintAttributes;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
@@ -49,7 +51,6 @@ import android.widget.AbsoluteLayout;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.OutputStream;
import java.util.Map;
/**
@@ -498,6 +499,8 @@ public class WebView extends AbsoluteLayout
ensureProviderCreated();
mProvider.init(javaScriptInterfaces, privateBrowsing);
+ // Post condition of creating a webview is the CookieSyncManager instance exists.
+ CookieSyncManager.createInstance(getContext());
}
/**
@@ -1040,7 +1043,9 @@ public class WebView extends AbsoluteLayout
* Exports the contents of this Webview as PDF. Only supported for API levels
* {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE} and above.
*
- * @param out The stream to export the PDF contents to. Cannot be null.
+ * TODO(sgurun) the parameter list is stale. Fix it before unhiding.
+ *
+ * @param fd The FileDescriptor to export the PDF contents to. Cannot be null.
* @param width The page width. Should be larger than 0.
* @param height The page height. Should be larger than 0.
* @param resultCallback A callback to be invoked when the PDF content is exported.
@@ -1049,21 +1054,26 @@ public class WebView extends AbsoluteLayout
* be null.
*
* The PDF conversion is done asynchronously and the PDF output is written to the provided
- * outputstream. The caller should not close the outputstream until the resultCallback is
- * called, indicating PDF conversion is complete. Webview cannot be drawn during the pdf
- * export so the application is recommended to take it offscreen, or putting in a layer
- * with an overlaid progress UI / spinner.
+ * file descriptor. The caller should not close the file descriptor until the resultCallback
+ * is called, indicating PDF conversion is complete. Webview will never close the file
+ * descriptor.
+ * Limitations: Webview cannot be drawn during the PDF export so the application is
+ * recommended to take it offscreen, or putting in a layer with an overlaid progress
+ * UI / spinner.
*
* If the caller cancels the task using the cancellationSignal, the cancellation will be
* acked using the resultCallback signal.
*
+ * Throws an exception if an IO error occurs accessing the file descriptor.
+ *
* TODO(sgurun) margins, explain the units, make it public.
* @hide
*/
- public void exportToPdf(OutputStream out, int width, int height,
- ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal) {
+ public void exportToPdf(ParcelFileDescriptor fd, PrintAttributes attributes,
+ ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal)
+ throws java.io.IOException {
checkThread();
- mProvider.exportToPdf(out, width, height, resultCallback, cancellationSignal);
+ mProvider.exportToPdf(fd, attributes, resultCallback, cancellationSignal);
}
/**
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index db98d30..b1a7878 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -62,6 +62,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.print.PrintAttributes;
import android.security.KeyChain;
import android.text.Editable;
import android.text.InputType;
@@ -2896,11 +2897,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
* See {@link WebView#exportToPdf()}
*/
@Override
- public void exportToPdf(java.io.OutputStream out, int width, int height,
- ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal) {
+ public void exportToPdf(android.os.ParcelFileDescriptor fd, PrintAttributes attributes,
+ ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal)
+ throws java.io.IOException {
// K-only API not implemented in WebViewClassic.
throw new IllegalStateException("This API not supported on Android 4.3 and earlier");
-
}
/**
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 8fe6edf..d625d8a 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -27,6 +27,8 @@ import android.net.http.SslCertificate;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.print.PrintAttributes;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -41,7 +43,6 @@ import android.webkit.WebView.PictureListener;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.OutputStream;
import java.util.Map;
/**
@@ -148,8 +149,9 @@ public interface WebViewProvider {
public Picture capturePicture();
- public void exportToPdf(OutputStream out, int width, int height,
- ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal);
+ public void exportToPdf(ParcelFileDescriptor fd, PrintAttributes attributes,
+ ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal)
+ throws java.io.IOException;
public float getScale();
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 109fcfe..54cc3f4 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -251,14 +251,14 @@ public class GridLayout extends ViewGroup {
// Instance variables
- final Axis horizontalAxis = new Axis(true);
- final Axis verticalAxis = new Axis(false);
- int orientation = DEFAULT_ORIENTATION;
- boolean useDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
- int alignmentMode = DEFAULT_ALIGNMENT_MODE;
- int defaultGap;
- int lastLayoutParamsHashCode = UNINITIALIZED_HASH;
- Printer printer = LOG_PRINTER;
+ final Axis mHorizontalAxis = new Axis(true);
+ final Axis mVerticalAxis = new Axis(false);
+ int mOrientation = DEFAULT_ORIENTATION;
+ boolean mUseDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
+ int mAlignmentMode = DEFAULT_ALIGNMENT_MODE;
+ int mDefaultGap;
+ int mLastLayoutParamsHashCode = UNINITIALIZED_HASH;
+ Printer mPrinter = LOG_PRINTER;
// Constructors
@@ -267,7 +267,7 @@ public class GridLayout extends ViewGroup {
*/
public GridLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- defaultGap = context.getResources().getDimensionPixelOffset(R.dimen.default_gap);
+ mDefaultGap = context.getResources().getDimensionPixelOffset(R.dimen.default_gap);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout);
try {
setRowCount(a.getInt(ROW_COUNT, DEFAULT_COUNT));
@@ -309,7 +309,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_orientation
*/
public int getOrientation() {
- return orientation;
+ return mOrientation;
}
/**
@@ -349,8 +349,8 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_orientation
*/
public void setOrientation(int orientation) {
- if (this.orientation != orientation) {
- this.orientation = orientation;
+ if (this.mOrientation != orientation) {
+ this.mOrientation = orientation;
invalidateStructure();
requestLayout();
}
@@ -369,7 +369,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_rowCount
*/
public int getRowCount() {
- return verticalAxis.getCount();
+ return mVerticalAxis.getCount();
}
/**
@@ -384,7 +384,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_rowCount
*/
public void setRowCount(int rowCount) {
- verticalAxis.setCount(rowCount);
+ mVerticalAxis.setCount(rowCount);
invalidateStructure();
requestLayout();
}
@@ -402,7 +402,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_columnCount
*/
public int getColumnCount() {
- return horizontalAxis.getCount();
+ return mHorizontalAxis.getCount();
}
/**
@@ -417,7 +417,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_columnCount
*/
public void setColumnCount(int columnCount) {
- horizontalAxis.setCount(columnCount);
+ mHorizontalAxis.setCount(columnCount);
invalidateStructure();
requestLayout();
}
@@ -433,7 +433,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_useDefaultMargins
*/
public boolean getUseDefaultMargins() {
- return useDefaultMargins;
+ return mUseDefaultMargins;
}
/**
@@ -463,7 +463,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_useDefaultMargins
*/
public void setUseDefaultMargins(boolean useDefaultMargins) {
- this.useDefaultMargins = useDefaultMargins;
+ this.mUseDefaultMargins = useDefaultMargins;
requestLayout();
}
@@ -480,7 +480,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_alignmentMode
*/
public int getAlignmentMode() {
- return alignmentMode;
+ return mAlignmentMode;
}
/**
@@ -499,7 +499,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_alignmentMode
*/
public void setAlignmentMode(int alignmentMode) {
- this.alignmentMode = alignmentMode;
+ this.mAlignmentMode = alignmentMode;
requestLayout();
}
@@ -514,7 +514,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_rowOrderPreserved
*/
public boolean isRowOrderPreserved() {
- return verticalAxis.isOrderPreserved();
+ return mVerticalAxis.isOrderPreserved();
}
/**
@@ -534,7 +534,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_rowOrderPreserved
*/
public void setRowOrderPreserved(boolean rowOrderPreserved) {
- verticalAxis.setOrderPreserved(rowOrderPreserved);
+ mVerticalAxis.setOrderPreserved(rowOrderPreserved);
invalidateStructure();
requestLayout();
}
@@ -550,7 +550,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_columnOrderPreserved
*/
public boolean isColumnOrderPreserved() {
- return horizontalAxis.isOrderPreserved();
+ return mHorizontalAxis.isOrderPreserved();
}
/**
@@ -570,7 +570,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_columnOrderPreserved
*/
public void setColumnOrderPreserved(boolean columnOrderPreserved) {
- horizontalAxis.setOrderPreserved(columnOrderPreserved);
+ mHorizontalAxis.setOrderPreserved(columnOrderPreserved);
invalidateStructure();
requestLayout();
}
@@ -581,9 +581,11 @@ public class GridLayout extends ViewGroup {
* @see #setPrinter(android.util.Printer)
*
* @return the printer associated with this view
+ *
+ * @hide
*/
public Printer getPrinter() {
- return printer;
+ return mPrinter;
}
/**
@@ -593,9 +595,11 @@ public class GridLayout extends ViewGroup {
* @param printer the printer associated with this layout
*
* @see #getPrinter()
+ *
+ * @hide
*/
public void setPrinter(Printer printer) {
- this.printer = (printer == null) ? NO_PRINTER : printer;
+ this.mPrinter = (printer == null) ? NO_PRINTER : printer;
}
// Static utility methods
@@ -643,7 +647,7 @@ public class GridLayout extends ViewGroup {
if (c.getClass() == Space.class) {
return 0;
}
- return defaultGap / 2;
+ return mDefaultGap / 2;
}
private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
@@ -651,11 +655,11 @@ public class GridLayout extends ViewGroup {
}
private int getDefaultMargin(View c, LayoutParams p, boolean horizontal, boolean leading) {
- if (!useDefaultMargins) {
+ if (!mUseDefaultMargins) {
return 0;
}
Spec spec = horizontal ? p.columnSpec : p.rowSpec;
- Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
Interval span = spec.span;
boolean leading1 = (horizontal && isLayoutRtl()) ? !leading : leading;
boolean isAtEdge = leading1 ? (span.min == 0) : (span.max == axis.getCount());
@@ -672,10 +676,10 @@ public class GridLayout extends ViewGroup {
}
private int getMargin(View view, boolean horizontal, boolean leading) {
- if (alignmentMode == ALIGN_MARGINS) {
+ if (mAlignmentMode == ALIGN_MARGINS) {
return getMargin1(view, horizontal, leading);
} else {
- Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
int[] margins = leading ? axis.getLeadingMargins() : axis.getTrailingMargins();
LayoutParams lp = getLayoutParams(view);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
@@ -722,8 +726,8 @@ public class GridLayout extends ViewGroup {
// install default indices for cells that don't define them
private void validateLayoutParams() {
- final boolean horizontal = (orientation == HORIZONTAL);
- final Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ final boolean horizontal = (mOrientation == HORIZONTAL);
+ final Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
final int count = (axis.definedCount != UNDEFINED) ? axis.definedCount : 0;
int major = 0;
@@ -779,9 +783,9 @@ public class GridLayout extends ViewGroup {
}
private void invalidateStructure() {
- lastLayoutParamsHashCode = UNINITIALIZED_HASH;
- horizontalAxis.invalidateStructure();
- verticalAxis.invalidateStructure();
+ mLastLayoutParamsHashCode = UNINITIALIZED_HASH;
+ mHorizontalAxis.invalidateStructure();
+ mVerticalAxis.invalidateStructure();
// This can end up being done twice. Better twice than not at all.
invalidateValues();
}
@@ -789,9 +793,9 @@ public class GridLayout extends ViewGroup {
private void invalidateValues() {
// Need null check because requestLayout() is called in View's initializer,
// before we are set up.
- if (horizontalAxis != null && verticalAxis != null) {
- horizontalAxis.invalidateValues();
- verticalAxis.invalidateValues();
+ if (mHorizontalAxis != null && mVerticalAxis != null) {
+ mHorizontalAxis.invalidateValues();
+ mVerticalAxis.invalidateValues();
}
}
@@ -822,7 +826,7 @@ public class GridLayout extends ViewGroup {
if (span.min != UNDEFINED && span.min < 0) {
handleInvalidParams(groupName + " indices must be positive");
}
- Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
int count = axis.definedCount;
if (count != UNDEFINED) {
if (span.max > count) {
@@ -908,7 +912,7 @@ public class GridLayout extends ViewGroup {
int right = getWidth() - getPaddingRight() - insets.right;
int bottom = getHeight() - getPaddingBottom() - insets.bottom;
- int[] xs = horizontalAxis.locations;
+ int[] xs = mHorizontalAxis.locations;
if (xs != null) {
for (int i = 0, length = xs.length; i < length; i++) {
int x = left + xs[i];
@@ -916,7 +920,7 @@ public class GridLayout extends ViewGroup {
}
}
- int[] ys = verticalAxis.locations;
+ int[] ys = mVerticalAxis.locations;
if (ys != null) {
for (int i = 0, length = ys.length; i < length; i++) {
int y = top + ys[i];
@@ -973,11 +977,11 @@ public class GridLayout extends ViewGroup {
}
private void consistencyCheck() {
- if (lastLayoutParamsHashCode == UNINITIALIZED_HASH) {
+ if (mLastLayoutParamsHashCode == UNINITIALIZED_HASH) {
validateLayoutParams();
- lastLayoutParamsHashCode = computeLayoutParamsHashCode();
- } else if (lastLayoutParamsHashCode != computeLayoutParamsHashCode()) {
- printer.println("The fields of some layout parameters were modified in between "
+ mLastLayoutParamsHashCode = computeLayoutParamsHashCode();
+ } else if (mLastLayoutParamsHashCode != computeLayoutParamsHashCode()) {
+ mPrinter.println("The fields of some layout parameters were modified in between "
+ "layout operations. Check the javadoc for GridLayout.LayoutParams#rowSpec.");
invalidateStructure();
consistencyCheck();
@@ -1005,11 +1009,11 @@ public class GridLayout extends ViewGroup {
if (firstPass) {
measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, lp.height);
} else {
- boolean horizontal = (orientation == HORIZONTAL);
+ boolean horizontal = (mOrientation == HORIZONTAL);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
if (spec.alignment == FILL) {
Interval span = spec.span;
- Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
int[] locations = axis.getLocations();
int cellSize = locations[span.max] - locations[span.min];
int viewSize = cellSize - getTotalMargin(c, horizontal);
@@ -1048,14 +1052,14 @@ public class GridLayout extends ViewGroup {
int heightSansPadding;
// Use the orientation property to decide which axis should be laid out first.
- if (orientation == HORIZONTAL) {
- widthSansPadding = horizontalAxis.getMeasure(widthSpecSansPadding);
+ if (mOrientation == HORIZONTAL) {
+ widthSansPadding = mHorizontalAxis.getMeasure(widthSpecSansPadding);
measureChildrenWithMargins(widthSpecSansPadding, heightSpecSansPadding, false);
- heightSansPadding = verticalAxis.getMeasure(heightSpecSansPadding);
+ heightSansPadding = mVerticalAxis.getMeasure(heightSpecSansPadding);
} else {
- heightSansPadding = verticalAxis.getMeasure(heightSpecSansPadding);
+ heightSansPadding = mVerticalAxis.getMeasure(heightSpecSansPadding);
measureChildrenWithMargins(widthSpecSansPadding, heightSpecSansPadding, false);
- widthSansPadding = horizontalAxis.getMeasure(widthSpecSansPadding);
+ widthSansPadding = mHorizontalAxis.getMeasure(widthSpecSansPadding);
}
int measuredWidth = Math.max(widthSansPadding + hPadding, getSuggestedMinimumWidth());
@@ -1114,11 +1118,11 @@ public class GridLayout extends ViewGroup {
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
- horizontalAxis.layout(targetWidth - paddingLeft - paddingRight);
- verticalAxis.layout(targetHeight - paddingTop - paddingBottom);
+ mHorizontalAxis.layout(targetWidth - paddingLeft - paddingRight);
+ mVerticalAxis.layout(targetHeight - paddingTop - paddingBottom);
- int[] hLocations = horizontalAxis.getLocations();
- int[] vLocations = verticalAxis.getLocations();
+ int[] hLocations = mHorizontalAxis.getLocations();
+ int[] vLocations = mVerticalAxis.getLocations();
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
@@ -1145,8 +1149,8 @@ public class GridLayout extends ViewGroup {
Alignment hAlign = getAlignment(columnSpec.alignment, true);
Alignment vAlign = getAlignment(rowSpec.alignment, false);
- Bounds boundsX = horizontalAxis.getGroupBounds().getValue(i);
- Bounds boundsY = verticalAxis.getGroupBounds().getValue(i);
+ Bounds boundsX = mHorizontalAxis.getGroupBounds().getValue(i);
+ Bounds boundsY = mVerticalAxis.getGroupBounds().getValue(i);
// Gravity offsets: the location of the alignment group relative to its cell group.
int gravityOffsetX = hAlign.getGravityOffset(c, cellWidth - boundsX.size(true));
@@ -1571,7 +1575,7 @@ public class GridLayout extends ViewGroup {
removed.add(arc);
}
}
- printer.println(axisName + " constraints: " + arcsToString(culprits) +
+ mPrinter.println(axisName + " constraints: " + arcsToString(culprits) +
" are inconsistent; permanently removing: " + arcsToString(removed) + ". ");
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index aa94728..ab81a37 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -22,11 +22,13 @@ import com.android.internal.content.PackageMonitor;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.LabeledIntent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -45,7 +47,6 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
-import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
@@ -71,13 +72,13 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
private PackageManager mPm;
private boolean mAlwaysUseOption;
private boolean mShowExtended;
- private GridView mGrid;
+ private ListView mListView;
private Button mAlwaysButton;
private Button mOnceButton;
private int mIconDpi;
private int mIconSize;
private int mMaxColumns;
- private int mLastSelected = GridView.INVALID_POSITION;
+ private int mLastSelected = ListView.INVALID_POSITION;
private boolean mRegistered;
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -139,17 +140,15 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
finish();
return;
} else if (count > 1) {
- ap.mView = getLayoutInflater().inflate(R.layout.resolver_grid, null);
- mGrid = (GridView) ap.mView.findViewById(R.id.resolver_grid);
- mGrid.setAdapter(mAdapter);
- mGrid.setOnItemClickListener(this);
- mGrid.setOnItemLongClickListener(new ItemLongClickListener());
+ ap.mView = getLayoutInflater().inflate(R.layout.resolver_list, null);
+ mListView = (ListView) ap.mView.findViewById(R.id.resolver_list);
+ mListView.setAdapter(mAdapter);
+ mListView.setOnItemClickListener(this);
+ mListView.setOnItemLongClickListener(new ItemLongClickListener());
if (alwaysUseOption) {
- mGrid.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
-
- resizeGrid();
} else if (count == 1) {
startActivity(mAdapter.intentForPosition(0));
mPackageMonitor.unregister();
@@ -172,11 +171,11 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
mAlwaysUseOption = false;
}
}
- }
-
- void resizeGrid() {
- final int itemCount = mAdapter.getCount();
- mGrid.setNumColumns(Math.min(itemCount, mMaxColumns));
+ final int initialHighlight = mAdapter.getInitialHighlight();
+ if (initialHighlight >= 0) {
+ mListView.setItemChecked(initialHighlight, true);
+ onItemClick(null, null, initialHighlight, 0); // Other entries are not used
+ }
}
Drawable getIcon(Resources res, int resId) {
@@ -247,26 +246,26 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (mAlwaysUseOption) {
- final int checkedPos = mGrid.getCheckedItemPosition();
- final boolean enabled = checkedPos != GridView.INVALID_POSITION;
+ final int checkedPos = mListView.getCheckedItemPosition();
+ final boolean enabled = checkedPos != ListView.INVALID_POSITION;
mLastSelected = checkedPos;
mAlwaysButton.setEnabled(enabled);
mOnceButton.setEnabled(enabled);
if (enabled) {
- mGrid.setSelection(checkedPos);
+ mListView.setSelection(checkedPos);
}
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final int checkedPos = mGrid.getCheckedItemPosition();
- final boolean hasValidSelection = checkedPos != GridView.INVALID_POSITION;
+ final int checkedPos = mListView.getCheckedItemPosition();
+ final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
mAlwaysButton.setEnabled(hasValidSelection);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
- mGrid.smoothScrollToPosition(checkedPos);
+ mListView.smoothScrollToPosition(checkedPos);
}
mLastSelected = checkedPos;
} else {
@@ -276,7 +275,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
public void onButtonClick(View v) {
final int id = v.getId();
- startSelected(mGrid.getCheckedItemPosition(), id == R.id.button_always);
+ startSelected(mListView.getCheckedItemPosition(), id == R.id.button_always);
dismiss();
}
@@ -288,94 +287,103 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
}
protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) {
- if (alwaysCheck) {
- // Build a reasonable intent filter, based on what matched.
- IntentFilter filter = new IntentFilter();
+ // Build a reasonable intent filter, based on what matched.
+ IntentFilter filter = new IntentFilter();
- if (intent.getAction() != null) {
- filter.addAction(intent.getAction());
- }
- Set<String> categories = intent.getCategories();
- if (categories != null) {
- for (String cat : categories) {
- filter.addCategory(cat);
- }
+ if (intent.getAction() != null) {
+ filter.addAction(intent.getAction());
+ }
+ Set<String> categories = intent.getCategories();
+ if (categories != null) {
+ for (String cat : categories) {
+ filter.addCategory(cat);
}
- filter.addCategory(Intent.CATEGORY_DEFAULT);
-
- int cat = ri.match&IntentFilter.MATCH_CATEGORY_MASK;
- Uri data = intent.getData();
- if (cat == IntentFilter.MATCH_CATEGORY_TYPE) {
- String mimeType = intent.resolveType(this);
- if (mimeType != null) {
- try {
- filter.addDataType(mimeType);
- } catch (IntentFilter.MalformedMimeTypeException e) {
- Log.w("ResolverActivity", e);
- filter = null;
- }
+ }
+ filter.addCategory(Intent.CATEGORY_DEFAULT);
+
+ int cat = ri.match&IntentFilter.MATCH_CATEGORY_MASK;
+ Uri data = intent.getData();
+ if (cat == IntentFilter.MATCH_CATEGORY_TYPE) {
+ String mimeType = intent.resolveType(this);
+ if (mimeType != null) {
+ try {
+ filter.addDataType(mimeType);
+ } catch (IntentFilter.MalformedMimeTypeException e) {
+ Log.w("ResolverActivity", e);
+ filter = null;
}
}
- if (data != null && data.getScheme() != null) {
- // We need the data specification if there was no type,
- // OR if the scheme is not one of our magical "file:"
- // or "content:" schemes (see IntentFilter for the reason).
- if (cat != IntentFilter.MATCH_CATEGORY_TYPE
- || (!"file".equals(data.getScheme())
- && !"content".equals(data.getScheme()))) {
- filter.addDataScheme(data.getScheme());
-
- // Look through the resolved filter to determine which part
- // of it matched the original Intent.
- Iterator<PatternMatcher> pIt = ri.filter.schemeSpecificPartsIterator();
- if (pIt != null) {
- String ssp = data.getSchemeSpecificPart();
- while (ssp != null && pIt.hasNext()) {
- PatternMatcher p = pIt.next();
- if (p.match(ssp)) {
- filter.addDataSchemeSpecificPart(p.getPath(), p.getType());
- break;
- }
+ }
+ if (data != null && data.getScheme() != null) {
+ // We need the data specification if there was no type,
+ // OR if the scheme is not one of our magical "file:"
+ // or "content:" schemes (see IntentFilter for the reason).
+ if (cat != IntentFilter.MATCH_CATEGORY_TYPE
+ || (!"file".equals(data.getScheme())
+ && !"content".equals(data.getScheme()))) {
+ filter.addDataScheme(data.getScheme());
+
+ // Look through the resolved filter to determine which part
+ // of it matched the original Intent.
+ Iterator<PatternMatcher> pIt = ri.filter.schemeSpecificPartsIterator();
+ if (pIt != null) {
+ String ssp = data.getSchemeSpecificPart();
+ while (ssp != null && pIt.hasNext()) {
+ PatternMatcher p = pIt.next();
+ if (p.match(ssp)) {
+ filter.addDataSchemeSpecificPart(p.getPath(), p.getType());
+ break;
}
}
- Iterator<IntentFilter.AuthorityEntry> aIt = ri.filter.authoritiesIterator();
- if (aIt != null) {
- while (aIt.hasNext()) {
- IntentFilter.AuthorityEntry a = aIt.next();
- if (a.match(data) >= 0) {
- int port = a.getPort();
- filter.addDataAuthority(a.getHost(),
- port >= 0 ? Integer.toString(port) : null);
- break;
- }
+ }
+ Iterator<IntentFilter.AuthorityEntry> aIt = ri.filter.authoritiesIterator();
+ if (aIt != null) {
+ while (aIt.hasNext()) {
+ IntentFilter.AuthorityEntry a = aIt.next();
+ if (a.match(data) >= 0) {
+ int port = a.getPort();
+ filter.addDataAuthority(a.getHost(),
+ port >= 0 ? Integer.toString(port) : null);
+ break;
}
}
- pIt = ri.filter.pathsIterator();
- if (pIt != null) {
- String path = data.getPath();
- while (path != null && pIt.hasNext()) {
- PatternMatcher p = pIt.next();
- if (p.match(path)) {
- filter.addDataPath(p.getPath(), p.getType());
- break;
- }
+ }
+ pIt = ri.filter.pathsIterator();
+ if (pIt != null) {
+ String path = data.getPath();
+ while (path != null && pIt.hasNext()) {
+ PatternMatcher p = pIt.next();
+ if (p.match(path)) {
+ filter.addDataPath(p.getPath(), p.getType());
+ break;
}
}
}
}
+ }
- if (filter != null) {
- final int N = mAdapter.mList.size();
- ComponentName[] set = new ComponentName[N];
- int bestMatch = 0;
- for (int i=0; i<N; i++) {
- ResolveInfo r = mAdapter.mList.get(i).ri;
- set[i] = new ComponentName(r.activityInfo.packageName,
- r.activityInfo.name);
- if (r.match > bestMatch) bestMatch = r.match;
- }
+ if (filter != null) {
+ final int N = mAdapter.mList.size();
+ ComponentName[] set = new ComponentName[N];
+ int bestMatch = 0;
+ for (int i=0; i<N; i++) {
+ ResolveInfo r = mAdapter.mList.get(i).ri;
+ set[i] = new ComponentName(r.activityInfo.packageName,
+ r.activityInfo.name);
+ if (r.match > bestMatch) bestMatch = r.match;
+ }
+ if (alwaysCheck) {
getPackageManager().addPreferredActivity(filter, bestMatch, set,
intent.getComponent());
+ } else {
+ try {
+ AppGlobals.getPackageManager().setLastChosenActivity(intent,
+ intent.resolveTypeIfNeeded(getContentResolver()),
+ PackageManager.MATCH_DEFAULT_ONLY,
+ filter, bestMatch, intent.getComponent());
+ } catch (RemoteException re) {
+ Log.d(TAG, "Error calling setLastChosenActivity\n" + re);
+ }
}
}
@@ -410,11 +418,13 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
private final class ResolveListAdapter extends BaseAdapter {
private final Intent[] mInitialIntents;
private final List<ResolveInfo> mBaseResolveList;
+ private ResolveInfo mLastChosen;
private final Intent mIntent;
private final int mLaunchedFromUid;
private final LayoutInflater mInflater;
private List<DisplayResolveInfo> mList;
+ private int mInitialHighlight = -1;
public ResolveListAdapter(Context context, Intent intent,
Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid) {
@@ -436,14 +446,24 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
if (newItemCount == 0) {
// We no longer have any items... just finish the activity.
finish();
- } else if (newItemCount != oldItemCount) {
- resizeGrid();
}
}
+ public int getInitialHighlight() {
+ return mInitialHighlight;
+ }
+
private void rebuildList() {
List<ResolveInfo> currentResolveList;
+ try {
+ mLastChosen = AppGlobals.getPackageManager().getLastChosenActivity(
+ mIntent, mIntent.resolveTypeIfNeeded(getContentResolver()),
+ PackageManager.MATCH_DEFAULT_ONLY);
+ } catch (RemoteException re) {
+ Log.d(TAG, "Error calling setLastChosenActivity\n" + re);
+ }
+
mList.clear();
if (mBaseResolveList != null) {
currentResolveList = mBaseResolveList;
@@ -556,6 +576,12 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
// Process labels from start to i
int num = end - start+1;
if (num == 1) {
+ if (mLastChosen != null
+ && mLastChosen.activityInfo.packageName.equals(
+ ro.activityInfo.packageName)
+ && mLastChosen.activityInfo.name.equals(ro.activityInfo.name)) {
+ mInitialHighlight = mList.size();
+ }
// No duplicate labels. Use label for entry at start
mList.add(new DisplayResolveInfo(ro, roLabel, null, null));
} else {
@@ -585,6 +611,12 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
}
for (int k = start; k <= end; k++) {
ResolveInfo add = rList.get(k);
+ if (mLastChosen != null
+ && mLastChosen.activityInfo.packageName.equals(
+ add.activityInfo.packageName)
+ && mLastChosen.activityInfo.name.equals(add.activityInfo.name)) {
+ mInitialHighlight = mList.size();
+ }
if (usePkg) {
// Use application name for all entries from start to end-1
mList.add(new DisplayResolveInfo(add, roLabel,
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index fd9fbae..eea9ee1 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -5,6 +5,7 @@
#include "GraphicsJNI.h"
#include "SkDither.h"
#include "SkUnPreMultiply.h"
+#include "SkStream.h"
#include <binder/Parcel.h>
#include "android_os_Parcel.h"
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index c433874..16beb02 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -202,7 +202,7 @@ private:
// since we "may" create a purgeable imageref, we require the stream be ref'able
// i.e. dynamically allocated, since its lifetime may exceed the current stack
// frame.
-static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
+static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding,
jobject options, bool allowPurgeable, bool forcePurgeable = false) {
int sampleSize = 1;
@@ -459,26 +459,17 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA
jobject padding, jobject options) {
jobject bitmap = NULL;
- SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 0);
+ SkAutoTUnref<SkStreamRewindable> stream(GetRewindableStream(env, is, storage));
- if (stream) {
+ if (stream.get()) {
// for now we don't allow purgeable with java inputstreams
+ // FIXME: GetRewindableStream may have made a copy, in which case
+ // purgeable should be allowed.
bitmap = doDecode(env, stream, padding, options, false, false);
- stream->unref();
}
return bitmap;
}
-static ssize_t getFDSize(int fd) {
- off64_t curr = ::lseek64(fd, 0, SEEK_CUR);
- if (curr < 0) {
- return 0;
- }
- size_t size = ::lseek(fd, 0, SEEK_END);
- ::lseek64(fd, curr, SEEK_SET);
- return size;
-}
-
static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor,
jobject padding, jobject bitmapFactoryOptions) {
@@ -512,44 +503,16 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
}
-/* make a deep copy of the asset, and return it as a stream, or NULL if there
- was an error.
- */
-static SkStream* copyAssetToStream(Asset* asset) {
- // if we could "ref/reopen" the asset, we may not need to copy it here
- off64_t size = asset->seek(0, SEEK_SET);
- if ((off64_t)-1 == size) {
- SkDebugf("---- copyAsset: asset rewind failed\n");
- return NULL;
- }
-
- size = asset->getLength();
- if (size <= 0) {
- SkDebugf("---- copyAsset: asset->getLength() returned %d\n", size);
- return NULL;
- }
-
- SkStream* stream = new SkMemoryStream(size);
- void* data = const_cast<void*>(stream->getMemoryBase());
- off64_t len = asset->read(data, size);
- if (len != size) {
- SkDebugf("---- copyAsset: asset->read(%d) returned %d\n", size, len);
- delete stream;
- stream = NULL;
- }
- return stream;
-}
-
static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
jobject padding, jobject options) {
- SkStream* stream;
+ SkStreamRewindable* stream;
Asset* asset = reinterpret_cast<Asset*>(native_asset);
bool forcePurgeable = optionsPurgeable(env, options);
if (forcePurgeable) {
// if we could "ref/reopen" the asset, we may not need to copy it here
// and we could assume optionsShareable, since assets are always RO
- stream = copyAssetToStream(asset);
+ stream = CopyAssetToStream(asset);
if (stream == NULL) {
return NULL;
}
@@ -559,7 +522,7 @@ static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
stream = new AssetStreamAdaptor(asset);
}
SkAutoUnref aur(stream);
- return doDecode(env, stream, padding, options, true, forcePurgeable);
+ return doDecode(env, stream, padding, options, forcePurgeable, forcePurgeable);
}
static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
@@ -572,7 +535,7 @@ static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
*/
bool purgeable = optionsPurgeable(env, options) && !optionsJustBounds(env, options);
AutoJavaByteArray ar(env, byteArray);
- SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, purgeable);
+ SkMemoryStream* stream = new SkMemoryStream(ar.ptr() + offset, length, purgeable);
SkAutoUnref aur(stream);
return doDecode(env, stream, NULL, options, purgeable);
}
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 8867a11..6646579 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -76,27 +76,6 @@ private:
int fHeight;
};
-static SkMemoryStream* buildSkMemoryStream(SkStream *stream) {
- size_t bufferSize = 4096;
- size_t streamLen = 0;
- size_t len;
- char* data = (char*)sk_malloc_throw(bufferSize);
-
- while ((len = stream->read(data + streamLen,
- bufferSize - streamLen)) != 0) {
- streamLen += len;
- if (streamLen == bufferSize) {
- bufferSize *= 2;
- data = (char*)sk_realloc_throw(data, bufferSize);
- }
- }
- data = (char*)sk_realloc_throw(data, streamLen);
-
- SkMemoryStream* streamMem = new SkMemoryStream();
- streamMem->setMemoryOwned(data, streamLen);
- return streamMem;
-}
-
static jobject createBitmapRegionDecoder(JNIEnv* env, SkStream* stream) {
SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
int width, height;
@@ -161,14 +140,12 @@ static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
jbyteArray storage, // byte[]
jboolean isShareable) {
jobject brd = NULL;
- SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024);
+ // for now we don't allow shareable with java inputstreams
+ SkStream* stream = CopyJavaInputStream(env, is, storage);
if (stream) {
- // for now we don't allow shareable with java inputstreams
- SkMemoryStream* mStream = buildSkMemoryStream(stream);
- brd = createBitmapRegionDecoder(env, mStream);
- SkSafeUnref(mStream); // the decoder now holds a reference
- stream->unref();
+ brd = createBitmapRegionDecoder(env, stream);
+ stream->unref(); // the decoder now holds a reference
}
return brd;
}
@@ -176,14 +153,14 @@ static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
jint native_asset, // Asset
jboolean isShareable) {
- SkStream* stream, *assStream;
Asset* asset = reinterpret_cast<Asset*>(native_asset);
- assStream = new AssetStreamAdaptor(asset);
- stream = buildSkMemoryStream(assStream);
- assStream->unref();
+ SkAutoTUnref<SkMemoryStream> stream(CopyAssetToStream(asset));
+ if (NULL == stream.get()) {
+ return NULL;
+ }
- jobject brd = createBitmapRegionDecoder(env, stream);
- SkSafeUnref(stream); // the decoder now holds a reference
+ jobject brd = createBitmapRegionDecoder(env, stream.get());
+ // The decoder now holds a reference to stream.
return brd;
}
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index aa4cbde..797d155 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -1,28 +1,83 @@
#include "CreateJavaOutputStreamAdaptor.h"
+#include "JNIHelp.h"
+#include "SkData.h"
+#include "SkRefCnt.h"
+#include "SkStream.h"
+#include "SkTypes.h"
+#include "Utils.h"
+#include <androidfw/Asset.h>
#define RETURN_NULL_IF_NULL(value) \
do { if (!(value)) { SkASSERT(0); return NULL; } } while (false)
+#define RETURN_ZERO_IF_NULL(value) \
+ do { if (!(value)) { SkASSERT(0); return 0; } } while (false)
+
static jmethodID gInputStream_resetMethodID;
static jmethodID gInputStream_markMethodID;
-static jmethodID gInputStream_availableMethodID;
+static jmethodID gInputStream_markSupportedMethodID;
static jmethodID gInputStream_readMethodID;
static jmethodID gInputStream_skipMethodID;
+class RewindableJavaStream;
+
+/**
+ * Non-rewindable wrapper for a Java InputStream.
+ */
class JavaInputStreamAdaptor : public SkStream {
public:
JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar)
: fEnv(env), fJavaInputStream(js), fJavaByteArray(ar) {
SkASSERT(ar);
- fCapacity = env->GetArrayLength(ar);
+ fCapacity = env->GetArrayLength(ar);
SkASSERT(fCapacity > 0);
- fBytesRead = 0;
+ fBytesRead = 0;
+ fIsAtEnd = false;
+ }
+
+ virtual size_t read(void* buffer, size_t size) {
+ JNIEnv* env = fEnv;
+ if (NULL == buffer) {
+ if (0 == size) {
+ return 0;
+ } else {
+ /* InputStream.skip(n) can return <=0 but still not be at EOF
+ If we see that value, we need to call read(), which will
+ block if waiting for more data, or return -1 at EOF
+ */
+ size_t amountSkipped = 0;
+ do {
+ size_t amount = this->doSkip(size - amountSkipped);
+ if (0 == amount) {
+ char tmp;
+ amount = this->doRead(&tmp, 1);
+ if (0 == amount) {
+ // if read returned 0, we're at EOF
+ fIsAtEnd = true;
+ break;
+ }
+ }
+ amountSkipped += amount;
+ } while (amountSkipped < size);
+ return amountSkipped;
+ }
+ }
+ return this->doRead(buffer, size);
+ }
+
+ virtual bool isAtEnd() const {
+ return fIsAtEnd;
}
- virtual bool rewind() {
+private:
+ // Does not override rewind, since a JavaInputStreamAdaptor's interface
+ // does not support rewinding. RewindableJavaStream, which is a friend,
+ // will be able to call this method to rewind.
+ bool doRewind() {
JNIEnv* env = fEnv;
fBytesRead = 0;
+ fIsAtEnd = false;
env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID);
if (env->ExceptionCheck()) {
@@ -53,6 +108,7 @@ public:
}
if (n < 0) { // n == 0 should not be possible, see InputStream read() specifications.
+ fIsAtEnd = true;
break; // eof
}
@@ -92,58 +148,19 @@ public:
return (size_t)skipped;
}
- size_t doSize() {
- JNIEnv* env = fEnv;
- jint avail = env->CallIntMethod(fJavaInputStream,
- gInputStream_availableMethodID);
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- SkDebugf("------- available threw an exception\n");
- avail = 0;
- }
- return avail;
- }
-
- virtual size_t read(void* buffer, size_t size) {
- JNIEnv* env = fEnv;
- if (NULL == buffer) {
- if (0 == size) {
- return this->doSize();
- } else {
- /* InputStream.skip(n) can return <=0 but still not be at EOF
- If we see that value, we need to call read(), which will
- block if waiting for more data, or return -1 at EOF
- */
- size_t amountSkipped = 0;
- do {
- size_t amount = this->doSkip(size - amountSkipped);
- if (0 == amount) {
- char tmp;
- amount = this->doRead(&tmp, 1);
- if (0 == amount) {
- // if read returned 0, we're at EOF
- break;
- }
- }
- amountSkipped += amount;
- } while (amountSkipped < size);
- return amountSkipped;
- }
- }
- return this->doRead(buffer, size);
- }
-
-private:
JNIEnv* fEnv;
jobject fJavaInputStream; // the caller owns this object
jbyteArray fJavaByteArray; // the caller owns this object
size_t fCapacity;
size_t fBytesRead;
+ bool fIsAtEnd;
+
+ // Allows access to doRewind and fBytesRead.
+ friend class RewindableJavaStream;
};
-SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
- jbyteArray storage, int markSize) {
+SkStream* WrapJavaInputStream(JNIEnv* env, jobject stream,
+ jbyteArray storage) {
static bool gInited;
if (!gInited) {
@@ -154,8 +171,8 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
"reset", "()V");
gInputStream_markMethodID = env->GetMethodID(inputStream_Clazz,
"mark", "(I)V");
- gInputStream_availableMethodID = env->GetMethodID(inputStream_Clazz,
- "available", "()I");
+ gInputStream_markSupportedMethodID = env->GetMethodID(inputStream_Clazz,
+ "markSupported", "()Z");
gInputStream_readMethodID = env->GetMethodID(inputStream_Clazz,
"read", "([BII)I");
gInputStream_skipMethodID = env->GetMethodID(inputStream_Clazz,
@@ -163,18 +180,167 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
RETURN_NULL_IF_NULL(gInputStream_resetMethodID);
RETURN_NULL_IF_NULL(gInputStream_markMethodID);
- RETURN_NULL_IF_NULL(gInputStream_availableMethodID);
+ RETURN_NULL_IF_NULL(gInputStream_markSupportedMethodID);
RETURN_NULL_IF_NULL(gInputStream_readMethodID);
RETURN_NULL_IF_NULL(gInputStream_skipMethodID);
gInited = true;
}
- if (markSize) {
- env->CallVoidMethod(stream, gInputStream_markMethodID, markSize);
+ return new JavaInputStreamAdaptor(env, stream, storage);
+}
+
+static SkMemoryStream* adaptor_to_mem_stream(SkStream* adaptor) {
+ SkASSERT(adaptor != NULL);
+ SkDynamicMemoryWStream wStream;
+ const int bufferSize = 256 * 1024; // 256 KB, same as ViewStateSerializer.
+ uint8_t buffer[bufferSize];
+ do {
+ size_t bytesRead = adaptor->read(buffer, bufferSize);
+ wStream.write(buffer, bytesRead);
+ } while (!adaptor->isAtEnd());
+ SkAutoTUnref<SkData> data(wStream.copyToData());
+ return new SkMemoryStream(data.get());
+}
+
+SkMemoryStream* CopyJavaInputStream(JNIEnv* env, jobject stream,
+ jbyteArray storage) {
+ SkAutoTUnref<SkStream> adaptor(WrapJavaInputStream(env, stream, storage));
+ if (NULL == adaptor.get()) {
+ return NULL;
}
+ return adaptor_to_mem_stream(adaptor.get());
+}
- return new JavaInputStreamAdaptor(env, stream, storage);
+/**
+ * Wrapper for a Java InputStream which is rewindable and
+ * has a length.
+ */
+class RewindableJavaStream : public SkStreamRewindable {
+public:
+ // RewindableJavaStream takes ownership of adaptor.
+ RewindableJavaStream(JavaInputStreamAdaptor* adaptor, size_t length)
+ : fAdaptor(adaptor)
+ , fLength(length) {
+ SkASSERT(fAdaptor != NULL);
+ }
+
+ virtual ~RewindableJavaStream() {
+ fAdaptor->unref();
+ }
+
+ virtual bool rewind() {
+ return fAdaptor->doRewind();
+ }
+
+ virtual size_t read(void* buffer, size_t size) {
+ return fAdaptor->read(buffer, size);
+ }
+
+ virtual bool isAtEnd() const {
+ return fAdaptor->isAtEnd();
+ }
+
+ virtual size_t getLength() const {
+ return fLength;
+ }
+
+ virtual bool hasLength() const {
+ return true;
+ }
+
+ virtual SkStreamRewindable* duplicate() const {
+ // Duplicating this stream requires rewinding and
+ // reading, which modify this Stream (and could
+ // fail, leaving this one invalid).
+ SkASSERT(false);
+ return NULL;
+ }
+
+private:
+ JavaInputStreamAdaptor* fAdaptor;
+ const size_t fLength;
+};
+
+/**
+ * If jstream is a ByteArrayInputStream, return its remaining length. Otherwise
+ * return 0.
+ */
+static size_t get_length_from_byte_array_stream(JNIEnv* env, jobject jstream) {
+ static jclass byteArrayInputStream_Clazz;
+ static jfieldID countField;
+ static jfieldID posField;
+
+ byteArrayInputStream_Clazz = env->FindClass("java/io/ByteArrayInputStream");
+ RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
+
+ countField = env->GetFieldID(byteArrayInputStream_Clazz, "count", "I");
+ RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
+ posField = env->GetFieldID(byteArrayInputStream_Clazz, "pos", "I");
+ RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
+
+ if (env->IsInstanceOf(jstream, byteArrayInputStream_Clazz)) {
+ // Return the remaining length, to keep the same behavior of using the rest of the
+ // stream.
+ return env->GetIntField(jstream, countField) - env->GetIntField(jstream, posField);
+ }
+ return 0;
+}
+
+/**
+ * If jstream is a class that has a length, return it. Otherwise
+ * return 0.
+ * Only checks for a set of subclasses.
+ */
+static size_t get_length_if_supported(JNIEnv* env, jobject jstream) {
+ size_t len = get_length_from_byte_array_stream(env, jstream);
+ if (len > 0) {
+ return len;
+ }
+ return 0;
+}
+
+SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
+ jbyteArray storage) {
+ SkAutoTUnref<SkStream> adaptor(WrapJavaInputStream(env, stream, storage));
+ if (NULL == adaptor.get()) {
+ return NULL;
+ }
+
+ const size_t length = get_length_if_supported(env, stream);
+ if (length > 0 && env->CallBooleanMethod(stream, gInputStream_markSupportedMethodID)) {
+ // Set the readLimit for mark to the end of the stream, so it can
+ // be rewound regardless of how much has been read.
+ env->CallVoidMethod(stream, gInputStream_markMethodID, length);
+ // RewindableJavaStream will unref adaptor when it is destroyed.
+ return new RewindableJavaStream(static_cast<JavaInputStreamAdaptor*>(adaptor.detach()),
+ length);
+ }
+
+ return adaptor_to_mem_stream(adaptor.get());
+}
+
+android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject jstream) {
+ static jclass assetInputStream_Clazz;
+ static jmethodID getAssetIntMethodID;
+
+ assetInputStream_Clazz = env->FindClass("android/content/res/AssetManager$AssetInputStream");
+ RETURN_NULL_IF_NULL(assetInputStream_Clazz);
+
+ getAssetIntMethodID = env->GetMethodID(assetInputStream_Clazz, "getAssetInt", "()I");
+ RETURN_NULL_IF_NULL(getAssetIntMethodID);
+
+ if (!env->IsInstanceOf(jstream, assetInputStream_Clazz)) {
+ return NULL;
+ }
+
+ jint jasset = env->CallIntMethod(jstream, getAssetIntMethodID);
+ android::Asset* a = reinterpret_cast<android::Asset*>(jasset);
+ if (NULL == a) {
+ jniThrowNullPointerException(env, "NULL native asset");
+ return NULL;
+ }
+ return new android::AssetStreamAdaptor(a);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
index c34c96a..5218dc5 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
@@ -3,10 +3,70 @@
//#include <android_runtime/AndroidRuntime.h>
#include "jni.h"
-#include "SkStream.h"
-SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
- jbyteArray storage, int markSize = 0);
+namespace android {
+ class AssetStreamAdaptor;
+}
+
+class SkMemoryStream;
+class SkStream;
+class SkStreamRewindable;
+class SkWStream;
+
+/**
+ * Return an adaptor from a Java InputStream to an SkStream.
+ * @param env JNIEnv object.
+ * @param stream Pointer to Java InputStream.
+ * @param storage Java byte array for retrieving data from the
+ * Java InputStream.
+ * @return SkStream Simple subclass of SkStream which supports its
+ * basic methods like reading. Only valid until the calling
+ * function returns, since the Java InputStream is not managed
+ * by the SkStream.
+ */
+SkStream* WrapJavaInputStream(JNIEnv* env, jobject stream,
+ jbyteArray storage);
+
+/**
+ * Copy a Java InputStream.
+ * @param env JNIEnv object.
+ * @param stream Pointer to Java InputStream.
+ * @param storage Java byte array for retrieving data from the
+ * Java InputStream.
+ * @return SkMemoryStream The data in stream will be copied to a new
+ * SkMemoryStream.
+ * FIXME: Could return a more generic return type if ViewStateSerializer
+ * did not require an SkMemoryStream.
+ */
+SkMemoryStream* CopyJavaInputStream(JNIEnv* env, jobject stream,
+ jbyteArray storage);
+
+/**
+ * Get a rewindable stream from a Java InputStream.
+ * @param env JNIEnv object.
+ * @param stream Pointer to Java InputStream.
+ * @param storage Java byte array for retrieving data from the
+ * Java InputStream.
+ * @return SkStreamRewindable Either a wrapper around the Java
+ * InputStream, if possible, or a copy which is rewindable.
+ * Since it may be a wrapper, must not be used after the
+ * caller returns, like the result of WrapJavaInputStream.
+ */
+SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
+ jbyteArray storage);
+
+/**
+ * If the Java InputStream is an AssetInputStream, return an adaptor.
+ * This should not be used after the calling function returns, since
+ * the caller may close the asset. Returns NULL if the stream is
+ * not an AssetInputStream.
+ * @param env JNIEnv object.
+ * @param stream Pointer to Java InputStream.
+ * @return AssetStreamAdaptor representing the InputStream, or NULL.
+ * Must not be held onto.
+ */
+android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject stream);
+
SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
jbyteArray storage);
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index 4f64ff8..2eae841 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -1,8 +1,10 @@
+#include "ScopedLocalRef.h"
#include "SkMovie.h"
#include "SkStream.h"
#include "GraphicsJNI.h"
#include "SkTemplates.h"
#include "SkUtils.h"
+#include "Utils.h"
#include "CreateJavaOutputStreamAdaptor.h"
#include <androidfw/Asset.h>
@@ -83,9 +85,14 @@ static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
NPE_CHECK_RETURN_ZERO(env, istream);
- // what is the lifetime of the array? Can the skstream hold onto it?
- jbyteArray byteArray = env->NewByteArray(16*1024);
- SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
+ SkStreamRewindable* strm = CheckForAssetStream(env, istream);
+ jbyteArray byteArray = NULL;
+ ScopedLocalRef<jbyteArray> scoper(env, NULL);
+ if (NULL == strm) {
+ byteArray = env->NewByteArray(16*1024);
+ scoper.reset(byteArray);
+ strm = GetRewindableStream(env, istream, byteArray);
+ }
if (NULL == strm) {
return 0;
}
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index 9c02219..dff2b18 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -20,6 +20,7 @@
#include "SkCanvas.h"
#include "SkPicture.h"
+#include "SkStream.h"
#include "SkTemplates.h"
#include "CreateJavaOutputStreamAdaptor.h"
@@ -38,10 +39,9 @@ public:
static SkPicture* deserialize(JNIEnv* env, jobject, jobject jstream,
jbyteArray jstorage) {
SkPicture* picture = NULL;
- SkStream* strm = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
- if (strm) {
- picture = SkPicture::CreateFromStream(strm);
- delete strm;
+ SkAutoTUnref<SkStream> strm(WrapJavaInputStream(env, jstream, jstorage));
+ if (strm.get()) {
+ picture = SkPicture::CreateFromStream(strm.get());
}
return picture;
}
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index cf6977e..b7d1f3a 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -28,12 +28,28 @@ bool AssetStreamAdaptor::rewind() {
return true;
}
+size_t AssetStreamAdaptor::getLength() const {
+ return fAsset->getLength();
+}
+
+bool AssetStreamAdaptor::isAtEnd() const {
+ return fAsset->getRemainingLength() == 0;
+}
+
+SkStreamRewindable* AssetStreamAdaptor::duplicate() const {
+ SkASSERT(false);
+ // Cannot create a duplicate, since each AssetStreamAdaptor
+ // would be modifying the Asset.
+ //return new AssetStreamAdaptor(fAsset);
+ return NULL;
+}
+
size_t AssetStreamAdaptor::read(void* buffer, size_t size) {
ssize_t amount;
if (NULL == buffer) {
- if (0 == size) { // caller is asking us for our total length
- return fAsset->getLength();
+ if (0 == size) {
+ return 0;
}
// asset->seek returns new total offset
// we want to return amount that was skipped
@@ -62,6 +78,34 @@ size_t AssetStreamAdaptor::read(void* buffer, size_t size) {
return amount;
}
+SkMemoryStream* android::CopyAssetToStream(Asset* asset) {
+ if (NULL == asset) {
+ return NULL;
+ }
+
+ off64_t size = asset->seek(0, SEEK_SET);
+ if ((off64_t)-1 == size) {
+ SkDebugf("---- copyAsset: asset rewind failed\n");
+ return NULL;
+ }
+
+ size = asset->getLength();
+ if (size <= 0) {
+ SkDebugf("---- copyAsset: asset->getLength() returned %d\n", size);
+ return NULL;
+ }
+
+ SkMemoryStream* stream = new SkMemoryStream(size);
+ void* data = const_cast<void*>(stream->getMemoryBase());
+ off64_t len = asset->read(data, size);
+ if (len != size) {
+ SkDebugf("---- copyAsset: asset->read(%d) returned %d\n", size, len);
+ delete stream;
+ stream = NULL;
+ }
+ return stream;
+}
+
jobject android::nullObjectReturn(const char msg[]) {
if (msg) {
SkDebugf("--- %s\n", msg);
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index 75ceaa2..a1ac72a 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -26,16 +26,27 @@
namespace android {
-class AssetStreamAdaptor : public SkStream {
+class AssetStreamAdaptor : public SkStreamRewindable {
public:
AssetStreamAdaptor(Asset* a) : fAsset(a) {}
virtual bool rewind();
virtual size_t read(void* buffer, size_t size);
+ virtual bool hasLength() const { return true; }
+ virtual size_t getLength() const;
+ virtual bool isAtEnd() const;
+ virtual SkStreamRewindable* duplicate() const;
private:
Asset* fAsset;
};
+/**
+ * Make a deep copy of the asset, and return it as a stream, or NULL if there
+ * was an error.
+ * FIXME: If we could "ref/reopen" the asset, we may not need to copy it here.
+ */
+
+SkMemoryStream* CopyAssetToStream(Asset*);
/** Restore the file descriptor's offset in our destructor
*/
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index faf6e63..9613df3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -207,6 +207,7 @@
<protected-broadcast android:name="android.intent.action.DREAMING_STARTED" />
<protected-broadcast android:name="android.intent.action.DREAMING_STOPPED" />
<protected-broadcast android:name="android.intent.action.ANY_DATA_STATE" />
+ <protected-broadcast android:name="android.intent.action.DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN" />
<protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
<protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
@@ -249,6 +250,9 @@
<protected-broadcast android:name="android.location.GPS_FIX_CHANGE" />
<protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
+ <protected-broadcast
+ android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
+
<!-- ====================================== -->
<!-- Permissions for things that cost money -->
<!-- ====================================== -->
@@ -1915,13 +1919,10 @@
android:description="@string/permdesc_bindNfcService"
android:protectionLevel="signature" />
- <!-- Allows an application to call APIs that give it access to all print jobs
- on the device. Usually an app can access only the print jobts it created.
- This permission is not available to third party applications.
- @hide -->
- <permission android:name="android.permission.ACCESS_ALL_PRINT_JOBS"
- android:label="@string/permlab_accessAllPrintJobs"
- android:description="@string/permdesc_accessAllPrintJobs"
+ <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it. -->
+ <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
+ android:label="@string/permlab_bindPrintSpoolerService"
+ android:description="@string/permdesc_bindPrintSpoolerService"
android:protectionLevel="signature" />
<!-- Must be required by a TextService (e.g. SpellCheckerService)
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 61cecae..28c5b74 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -18,40 +18,40 @@
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:gravity="center"
- android:orientation="vertical"
+ android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:background="@android:drawable/activity_picker_bg"
- android:padding="16dp">
-
- <!-- Extended activity info to distinguish between duplicate activity names -->
- <TextView android:id="@android:id/text2"
- android:textAppearance="?android:attr/textAppearance"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:minLines="2"
- android:maxLines="2"
- android:paddingStart="4dip"
- android:paddingEnd="4dip" />
+ android:background="@android:drawable/activity_picker_bg">
<!-- Activity icon when presenting dialog
Size will be filled in by ResolverActivity -->
<ImageView android:id="@+id/icon"
android:layout_width="0dp"
android:layout_height="0dp"
+ android:layout_marginStart="12dp"
+ android:padding="4dp"
android:scaleType="fitCenter" />
- <!-- Activity name -->
- <TextView android:id="@android:id/text1"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_width="wrap_content"
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:gravity="start|center_vertical"
+ android:orientation="vertical"
android:layout_height="wrap_content"
- android:gravity="center"
- android:minLines="2"
- android:maxLines="2"
- android:paddingStart="4dip"
- android:paddingEnd="4dip" />
+ android:layout_width="wrap_content"
+ android:layout_gravity="start|center_vertical"
+ android:layout_marginStart="12dp">
+ <!-- Activity name -->
+ <TextView android:id="@android:id/text1"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="2" />
+ <!-- Extended activity info to distinguish between duplicate activity names -->
+ <TextView android:id="@android:id/text2"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="2"
+ android:paddingTop="4dip" />
+ </LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/resolver_grid.xml b/core/res/res/layout/resolver_list.xml
index d271c1a..f88ced1 100644
--- a/core/res/res/layout/resolver_grid.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -23,20 +23,18 @@
android:divider="?android:attr/dividerHorizontal"
android:showDividers="middle"
android:dividerPadding="0dip">
+
<FrameLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
- <GridView
- android:layout_gravity="center"
- android:layout_width="wrap_content"
+
+ <ListView
+ android:layout_width="match_parent"
android:layout_height="match_parent"
- android:id="@+id/resolver_grid"
- android:numColumns="4"
- android:columnWidth="128dp"
- android:padding="16dp"
- android:clipToPadding="false"
- android:scrollbarStyle="outsideOverlay" />
+ android:id="@+id/resolver_list" />
+
</FrameLayout>
+
<LinearLayout
android:id="@+id/button_bar"
android:visibility="gone"
diff --git a/core/res/res/values-mcc208-mnc26/config.xml b/core/res/res/values-mcc208-mnc26/config.xml
new file mode 100644
index 0000000..31d2d0f
--- /dev/null
+++ b/core/res/res/values-mcc208-mnc26/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>20801</item>
+ <item>20810</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc04/config.xml b/core/res/res/values-mcc214-mnc04/config.xml
new file mode 100644
index 0000000..71301d5
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc04/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>21407</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc30/config.xml b/core/res/res/values-mcc234-mnc30/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc30/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc31/config.xml b/core/res/res/values-mcc234-mnc31/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc31/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc32/config.xml b/core/res/res/values-mcc234-mnc32/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc32/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc33/config.xml b/core/res/res/values-mcc234-mnc33/config.xml
index d79d212..175f76e 100644
--- a/core/res/res/values-mcc234-mnc33/config.xml
+++ b/core/res/res/values-mcc234-mnc33/config.xml
@@ -35,4 +35,14 @@
"name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">Consumer Broadband,consumerbroadband,,,,,,,,,234,33,,DUN</string>
+
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc234-mnc34/config.xml b/core/res/res/values-mcc234-mnc34/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc34/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc86/config.xml b/core/res/res/values-mcc234-mnc86/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc86/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
new file mode 100644
index 0000000..706570c
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>302</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
new file mode 100644
index 0000000..706570c
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>302</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc780/config.xml b/core/res/res/values-mcc302-mnc780/config.xml
index 42d4956..b03d14e 100644
--- a/core/res/res/values-mcc302-mnc780/config.xml
+++ b/core/res/res/values-mcc302-mnc780/config.xml
@@ -37,4 +37,8 @@
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">SaskTel Tethering,inet.stm.sk.ca,,,,,,,,,302,780,,DUN</string>
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>302</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc425-mnc07/config.xml b/core/res/res/values-mcc425-mnc07/config.xml
index 890420e..51a9934 100644
--- a/core/res/res/values-mcc425-mnc07/config.xml
+++ b/core/res/res/values-mcc425-mnc07/config.xml
@@ -37,4 +37,8 @@
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">PC HOT mobile,pc.hotm,,,,,,,,,425,07,,DUN</string>
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>42503</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc425-mnc08/config.xml b/core/res/res/values-mcc425-mnc08/config.xml
new file mode 100644
index 0000000..8470b86
--- /dev/null
+++ b/core/res/res/values-mcc425-mnc08/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>42502</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 50ea08b..5444cb1 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2602,6 +2602,9 @@
<!-- Short description of the functionality the service implements. This attribute
is mandatory.-->
<attr name="description" />
+ <!-- Whether the device must be unlocked before routing data to this service.
+ The default is false.-->
+ <attr name="requireDeviceUnlock" format="boolean"/>
</declare-styleable>
<!-- Use <code>offhost-apdu-service</code> as the root tag of the XML resource that
@@ -2622,7 +2625,8 @@
<!-- Short description of what the AID group implements. This attribute is mandatory.-->
<attr name="description" />
<!-- The category attribute will be used by the Android platform to present
- multiple applications that register AIDs in the same category uniformly.
+ multiple applications that register ISO 7816 Application IDs (AIDs) in the
+ same category uniformly.
Additionally, when a category is specified, Android will ensure that either
all AIDs in this group are routed to this application, or none at all.
This attribute is optional.-->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5d4383f..d4a408d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -820,6 +820,10 @@
<!-- IP address of the dns server to use if nobody else suggests one -->
<string name="config_default_dns_server" translatable="false">8.8.8.8</string>
+ <!-- The default mobile provisioning apn. Empty by default, maybe overridden by
+ an mcc/mnc specific config.xml -->
+ <string name="mobile_provisioning_apn" translatable="false"></string>
+
<!-- The default mobile provisioning url. Empty by default, maybe overridden by
an mcc/mnc specific config.xml -->
<string name="mobile_provisioning_url" translatable="false"></string>
@@ -1207,4 +1211,15 @@
<!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM -->
<integer name="config_toastDefaultGravity">0x00000051</integer>
+ <!-- set to false if we need to show user confirmation
+ when alpha identifier is not provided by the UICC -->
+ <bool name="config_stkNoAlphaUsrCnf">true</bool>
+
+ <!-- Don't use roaming icon for considered operators.
+ Can use mcc or mcc+mnc as item. For example, 302 or 21407.
+ If operators, 21404 and 21407, make roaming agreements, user of 21404 should not see
+ the roaming icon as using 21407 network.
+ To do this, add 21407 item to values-mcc214-mnc04/config.xml -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ </string-array>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f2ec04f..696e782 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2073,5 +2073,6 @@
<public type="attr" name="customRoots" />
<public type="attr" name="autoMirrored" />
<public type="attr" name="supportsSwitchingToNextInputMethod" />
+ <public type="attr" name="requireDeviceUnlock" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ead46c2..4b32e2b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -984,12 +984,13 @@
<string name="permdesc_bindPrintService">Allows the holder to bind to the top-level
interface of a print service. Should never be needed for normal apps.</string>
- <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_accessAllPrintJobs">access all print jobs</string>
- <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_accessAllPrintJobs">Allows the holder to access print jobs
- created by another app. Should never be needed for normal apps.</string>
-
+ <!-- Title of an application permission, listed so the user can choose
+ whether they want to allow the application to do this. -->
+ <string name="permlab_bindPrintSpoolerService">bind to a print spooler service</string>
+ <!-- Description of an application permission, listed so the user can
+ choose whether they want to allow the application to do this. -->
+ <string name="permdesc_bindPrintSpoolerService">Allows the holder to bind to the top-level
+ interface of a print spooler service. Should never be needed for normal apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_bindNfcService">bind to NFC service</string>
@@ -4292,6 +4293,9 @@
<!-- Write fail reason: couldn't write the printed content. [CHAR LIMIT=none] -->
<string name="write_fail_reason_cannot_write">Error writing content</string>
+ <!-- Print fail reason: unknown. [CHAR LIMIT=25] -->
+ <string name="reason_unknown">unknown</string>
+
<!-- PIN entry dialog label/hint for PIN [CHAR LIMIT=none] -->
<string name="restr_pin_enter_pin">Enter PIN</string>
<!-- PIN entry dialog label/hint for old PIN [CHAR LIMIT=none] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a9c812e..f008b10 100755..100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -668,6 +668,7 @@
<java-symbol type="string" name="preposition_for_time" />
<java-symbol type="string" name="progress_erasing" />
<java-symbol type="string" name="progress_unmounting" />
+ <java-symbol type="string" name="mobile_provisioning_apn" />
<java-symbol type="string" name="mobile_provisioning_url" />
<java-symbol type="string" name="mobile_redirected_provisioning_url" />
<java-symbol type="string" name="reboot_safemode_confirm" />
@@ -868,6 +869,7 @@
<java-symbol type="string" name="mediaSize_na_junior_legal" />
<java-symbol type="string" name="mediaSize_na_ledger" />
<java-symbol type="string" name="mediaSize_na_tabloid" />
+ <java-symbol type="string" name="reason_unknown" />
<java-symbol type="string" name="restr_pin_enter_pin" />
<java-symbol type="string" name="write_fail_reason_cancelled" />
<java-symbol type="string" name="write_fail_reason_cannot_write" />
@@ -910,6 +912,7 @@
<java-symbol type="array" name="config_masterVolumeRamp" />
<java-symbol type="array" name="config_cdma_dun_supported_types" />
<java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" />
+ <java-symbol type="array" name="config_operatorConsideredNonRoaming" />
<java-symbol type="drawable" name="default_wallpaper" />
<java-symbol type="drawable" name="indicator_input_error" />
@@ -1526,8 +1529,8 @@
<java-symbol type="string" name="enable_explore_by_touch_warning_title" />
<java-symbol type="string" name="enable_explore_by_touch_warning_message" />
- <java-symbol type="layout" name="resolver_grid" />
- <java-symbol type="id" name="resolver_grid" />
+ <java-symbol type="layout" name="resolver_list" />
+ <java-symbol type="id" name="resolver_list" />
<java-symbol type="id" name="button_once" />
<java-symbol type="id" name="button_always" />
<java-symbol type="integer" name="config_maxResolverActivityColumns" />
@@ -1639,6 +1642,7 @@
<java-symbol type="bool" name="config_sf_slowBlur" />
<java-symbol type="drawable" name="ic_volume" />
<java-symbol type="drawable" name="stat_notify_sim_toolkit" />
+ <java-symbol type="bool" name="config_stkNoAlphaUsrCnf" />
<!-- From maps library -->
<java-symbol type="array" name="maps_starting_lat_lng" />