Merge "JB MR2 == API 18." into jb-mr2-dev
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 9e9b43d..e5d6e51 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -129,4 +129,6 @@
void captivePortalCheckComplete(in NetworkInfo info);
void supplyMessenger(int networkType, in Messenger messenger);
+
+ int findConnectionTypeForIface(in String iface);
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 3df7258..906f02d 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -226,7 +226,12 @@
private boolean mMeasureVerticalWithPaddingMargin = false;
// A default width used for RTL measure pass
- private static final int DEFAULT_WIDTH = Integer.MAX_VALUE / 2;
+ /**
+ * Value reduced so as not to interfere with View's measurement spec. flags. See:
+ * {@link View#MEASURED_SIZE_MASK}.
+ * {@link View#MEASURED_STATE_TOO_SMALL}.
+ **/
+ private static final int DEFAULT_WIDTH = 0x008000000;
public RelativeLayout(Context context) {
super(context);
diff --git a/docs/html/distribute/googleplay/about/monetizing.jd b/docs/html/distribute/googleplay/about/monetizing.jd
index 8233a31..9a5c6d7 100644
--- a/docs/html/distribute/googleplay/about/monetizing.jd
+++ b/docs/html/distribute/googleplay/about/monetizing.jd
@@ -138,7 +138,7 @@
<h2 id="payouts">Monthly payouts in your local currency</h2>
<p>To sell products in Google Play, all you have to do is register for a Google
-Checkout merchant account and link it to your Google Play Android Developer
+Wallet merchant account and link it to your Google Play Android Developer
Console account (see <a
href="{@docRoot}distribute/googleplay/publish/register.html">Get Started with
Publishing</a> for details). Once you’ve set up your account and published your
@@ -159,4 +159,4 @@
<p>At the close of the month, you can download a complete sales report that
gives you the final details of all transactions that closed in the month,
including the payout amounts and other data. Additional financial reports are
-available in your Google Checkout merchant account.</p>
+available in your Google Wallet merchant account.</p>
diff --git a/docs/html/distribute/googleplay/publish/console.jd b/docs/html/distribute/googleplay/publish/console.jd
index 0bf5e78..3831e51 100644
--- a/docs/html/distribute/googleplay/publish/console.jd
+++ b/docs/html/distribute/googleplay/publish/console.jd
@@ -64,8 +64,8 @@
<h3 id="merchant">Linking your Merchant Account</h3>
<p>If you want to sell apps or in-app products, you can link your Google
-Checkout Merchant account to your developer profile. Google Play uses the linked
-Checkout account for financial and tax identification and monthly payouts of
+Wallet merchant account to your developer profile. Google Play uses the linked
+merchant account for financial and tax identification and monthly payouts of
sales. </p>
<h3 id="details">Your store listing details</h3>
diff --git a/docs/html/distribute/googleplay/publish/preparing.jd b/docs/html/distribute/googleplay/publish/preparing.jd
index 416f02e..b4b8c226 100644
--- a/docs/html/distribute/googleplay/publish/preparing.jd
+++ b/docs/html/distribute/googleplay/publish/preparing.jd
@@ -278,7 +278,7 @@
</ul>
<p> If your app is be priced, or if you'll be selling in-app products,
-you need set up a Checkout Merchant Account before you can publish.</p>
+you need set up a Google Wallet merchant account before you can publish.</p>
<table>
<tr>
@@ -560,7 +560,7 @@
<p>Make sure that: </p>
<ul>
-<li>Your developer profile has the correct information and is linked to the proper Google Checkout Merchant account (if you are selling products).</li>
+<li>Your developer profile has the correct information and is linked to the proper Google Wallet merchant account (if you are selling products).</li>
<li>You have the right version of the app uploaded.</li>
<li>All parts of your Product Details are ready, including all graphic assets, screenshots, video, localized descriptions, and so on. </li>
<li>You have set your app's pricing to free or priced.</li>
diff --git a/docs/html/distribute/googleplay/publish/register.jd b/docs/html/distribute/googleplay/publish/register.jd
index 5f1f2ea..faade81 100644
--- a/docs/html/distribute/googleplay/publish/register.jd
+++ b/docs/html/distribute/googleplay/publish/register.jd
@@ -53,8 +53,8 @@
<li>Read and accept the <strong>Developer Distribution Agreement</strong> that applies to your
country or region. Note that apps and store listings that you publish on Google Play must comply
with the Developer Program Policies and US export law,</li>
-<li>Pay a <strong>$25 USD registration fee</strong> using Google Checkout. If you don't have
-a Google Checkout account, you can quickly set one up during the process.</li>
+<li>Pay a <strong>$25 USD registration fee</strong> using Google Wallet. If you don't have
+a Google Wallet account, you can quickly set one up during the process.</li>
</ol>
<p>When your registration is verified, you’ll be notified at the email address you specified during registration.</p>
diff --git a/docs/html/google/backup/signup.jd b/docs/html/google/backup/signup.jd
index d5c26a1..70f7de2 100644
--- a/docs/html/google/backup/signup.jd
+++ b/docs/html/google/backup/signup.jd
@@ -225,7 +225,7 @@
} else if ($("input#agree").is(':checked')
&& packagename.length
&& packagename != DEFAULT_TEXT) {
- window.location = "http://play.google.com/apps/publish/GetBackupApiKey?p=" +
+ window.location = "https://play.google.com/apps/publish/v2/GetBackupApiKey?p=" +
encodeURIComponent(packagename);
} else {
$("label#agreeLabel,label#pnameLabel").parent().stop().animate({color: "#258AAF"}, 200,
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 089baf5..6beb486 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -779,9 +779,9 @@
that restricts the traffic to or
from the Internet, you need to configure it to allow connectivity with GCM in order for
your Android devices to receive messages.
-The ports to open are: 5228, 5229, and 5230. GCM typically only uses 5228, but
-it sometimes uses 5229 and 5230. GCM doesn't provide specific IPs, so you should
-allow your firewall to accept incoming connections from all IP addresses
+The ports to open are: 5228, 5229, and 5230. GCM typically only uses 5228, but
+it sometimes uses 5229 and 5230. GCM doesn't provide specific IPs, so you should allow
+your firewall to accept outgoing connections to all IP addresses
contained in the IP blocks listed in Google's ASN of 15169.</p>
diff --git a/docs/html/google/play/billing/billing_admin.jd b/docs/html/google/play/billing/billing_admin.jd
index 91883da1..f1e4ec4 100644
--- a/docs/html/google/play/billing/billing_admin.jd
+++ b/docs/html/google/play/billing/billing_admin.jd
@@ -29,15 +29,15 @@
Developer Console, registering test accounts, and handling refunds when necessary.</p>
<p>You must have a Google Play publisher account to register test accounts. And you must have a
-Google Checkout merchant account to create a product list and issue refunds to your users. If you
+Google Wallet merchant account to create a product list and issue refunds to your users. If you
already have a publisher account on Google Play, you can use your existing account. You do not
need to register for a new account to support in-app billing.</p>
<p>If you do not have a publisher account, you can register as a Google Play
developer and set up a publisher account at the <a
href="http://play.google.com/apps/publish">Google Play Developer Console</a>. If you do not
-have a Google Checkout merchant account, you can register for one at the <a
-href="http://checkout.google.com">Google Checkout site</a>.</p>
+have a Google Wallet merchant account, you can register for one through the
+Developer Console.</p>
<h2 id="billing-list-setup">Creating a Product List</h2>
@@ -48,7 +48,7 @@
<p>You can access an application's product list by clicking the <strong>In-App Products</strong>
link in applications listed in your developer account (see
-figure 1). The <strong>In-App Products</strong> link appears only if you have a Google Checkout
+figure 1). The <strong>In-App Products</strong> link appears only if you have a Google Wallet
merchant account and the application's manifest includes the <code>com.android.vending.BILLING</code>
permission.</p>
@@ -67,7 +67,7 @@
</div>
<p>You can create a product list for any published application or any draft application that's been
-uploaded and saved to the Developer Console. However, you must have a Google Checkout merchant
+uploaded and saved to the Developer Console. However, you must have a Google Wallet merchant
account and the application's manifest must include the <code>com.android.vending.BILLING</code>
permission. If an application's manifest does not include this permission, you will be able to edit
existing items in the product list but you will not be able to add new items to the list. For more
@@ -401,22 +401,22 @@
<p>In-app billing does not allow users to send a refund request to Google Play. Refunds for
in-app purchases must be directed to you (the application developer). You can then process the
-refund through your Google Checkout merchant account. When you do this, Google Play receives a
-refund notification from Google Checkout, and Google Play sends a refund message to your
+refund through your Google Wallet merchant account. When you do this, Google Play receives a
+refund notification from Google Wallet, and Google Play sends a refund message to your
application. For more information, see <a
href="{@docRoot}google/play/billing/v2/api.html#billing-action-notify">Handling
IN_APP_NOTIFY messages</a> and <a
href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=1153485">In-app Billing
Pricing</a>.</p>
-<p class="caution"><strong>Important:</strong> You cannot use the Google Checkout API to issue
+<p class="caution"><strong>Important:</strong> You cannot use the Google Wallet API to issue
refunds or cancel In-app Billing transactions. You must do this manually through your Google
-Checkout merchant account. However, you can use the Google Checkout API to retrieve order
+Wallet merchant account. However, you can use the Google Wallet API to retrieve order
information.</p>
<h2 id="orderId">Working with Order Numbers</h2>
-<p>When a user purchases an in-app item, Google Checkout assigns the transaction
+<p>When a user purchases an in-app item, Google Wallet assigns the transaction
a unique and permanent order number. Google Play provides that order number to
you at the conclusion of the purchase flow, as the value of the
<code>orderId</code> field of the <code>PURCHASE_STATE_CHANGED</code>
@@ -428,9 +428,9 @@
customer support.</p>
<p>The order number itself is a string consisting of numbers only, with a format
-assigned and managed by Google Checkout.</p>
+assigned and managed by Google Wallet.</p>
-<p>For transactions dated 5 December 2012 or later, Google Checkout assigns a
+<p>For transactions dated 5 December 2012 or later, Google Wallet assigns a
Merchant Order Number (rather than a Google Order Number) and reports the Merchant
Order Number as the value of <code>orderID</code>. Here's an
example:</p>
diff --git a/docs/html/google/play/billing/billing_overview.jd b/docs/html/google/play/billing/billing_overview.jd
index 14cbfdf..581c648 100644
--- a/docs/html/google/play/billing/billing_overview.jd
+++ b/docs/html/google/play/billing/billing_overview.jd
@@ -10,7 +10,7 @@
<li>Use In-app Billing to sell digital goods, including one-time items and
recurring subscriptions.</li>
<li>Supported for any app published on Google Play. You only need a Google
-Play Developer Console account and a Google Checkout Merchant account.</li>
+Play Developer Console account and a Google Wallet merchant account.</li>
<li>Checkout processing is automatically handled by Google Play, with the
same look-and-feel as for app purchases.</li>
</ul>
@@ -119,8 +119,8 @@
<h2 id="checkout">Google Play Purchase Flow</h2>
<p>Google Play uses the same checkout backend service as is used for application
purchases, so your users experience a consistent and familiar purchase flow.</p>
-<p class="note"><strong>Important:</strong> You must have a Google Checkout
-Merchant account to use the In-app Billing service on Google Play.</p>
+<p class="note"><strong>Important:</strong> You must have a Google Wallet
+merchant account to use the In-app Billing service on Google Play.</p>
<p>To initiate a purchase, your application sends a billing request for a
specific in-app product. Google Play then handles all of the checkout details for
the transaction, including requesting and validating the form of payment and
diff --git a/docs/html/google/play/billing/billing_subscriptions.jd b/docs/html/google/play/billing/billing_subscriptions.jd
index 2840dbc..92725cf 100644
--- a/docs/html/google/play/billing/billing_subscriptions.jd
+++ b/docs/html/google/play/billing/billing_subscriptions.jd
@@ -53,7 +53,7 @@
<p>When users purchase subscriptions in your apps, Google Play handles all
checkout details so your apps never have to directly process any financial
transactions. Google Play processes all payments for subscriptions through
-Google Checkout, just as it does for standard in-app products and app purchases.
+Google Wallet, just as it does for standard in-app products and app purchases.
This ensures a consistent and familiar purchase flow for your users.</p>
<img src="{@docRoot}images/in-app-billing/v3/billing_subscription_v3.png" style="float:right; border:4px solid ddd;">
@@ -137,10 +137,10 @@
automated recurring billing at either of two intervals:</p>
<ul>
- <li>Monthly — Google Play bills the customer’s Google Checkout account at
+ <li>Monthly — Google Play bills the customer’s Google Wallet account at
the time of purchase and monthly subsequent to the purchase date (exact billing
intervals can vary slightly over time)</li>
- <li>Annually — Google Play bills the customer's Google Checkout account at
+ <li>Annually — Google Play bills the customer's Google Wallet account at
the time of purchase and again on the same date in subsequent years.</li>
</ul>
@@ -154,7 +154,7 @@
or by Direct Carrier Billing) that was originally used to purchase the
subscription.</p>
-<p>When the subscription payment is approved by Google Checkout, Google Play
+<p>When the subscription payment is approved by Google Wallet, Google Play
provides a purchase token back to the purchasing app through the In-app Billing
API. Your apps can store the token locally or pass it to your backend servers,
which can then use it to validate or cancel the subscription remotely using the <a
@@ -291,7 +291,7 @@
<h2 id="payment">Payment Processing and Policies</h2>
<p>In general, the terms of Google Play allow you to sell in-app subscriptions
-only through the standard payment processor, Google Checkout. For purchases of
+only through the standard payment processor, Google Wallet. For purchases of
any subscription products, the transaction fee is the same as the transaction
fee for application purchases (30%).</p>
@@ -306,7 +306,7 @@
<h3 id="orderId">Subscription order numbers</h3>
<p>To help you track transactions relating to a given subscription, Google
-Checkout provides a base Merchant Order Number for all recurrences of the
+Wallet provides a base Merchant Order Number for all recurrences of the
subscription and denotes
each recurring transaction by appending an integer as follows: </p>
diff --git a/docs/html/google/play/billing/billing_testing.jd b/docs/html/google/play/billing/billing_testing.jd
index 8dcaa86..241d45e 100644
--- a/docs/html/google/play/billing/billing_testing.jd
+++ b/docs/html/google/play/billing/billing_testing.jd
@@ -77,8 +77,8 @@
<p>When you make an In-app Billing request with this product ID, Google Play responds as
though the purchase was refunded. Refunds cannot be initiated through Google Play's in-app
billing service. Refunds must be initiated by you (the merchant). After you process a refund
- request through your Google Checkout account, a refund message is sent to your application by
- Google Play. This occurs only when Google Play gets notification from Google Checkout that
+ request through your Google Wallet merchant account, a refund message is sent to your application by
+ Google Play. This occurs only when Google Play gets notification from Google Wallet that
a refund has been made. For more information about refunds, see <a href="{@docRoot}google/play/billing/v2/api.html#billing-action-notify">Handling
IN_APP_NOTIFY messages</a> and <a href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=1153485">In-app Billing
Pricing</a>.</p>
@@ -200,7 +200,7 @@
<p>To test your In-app Billing implementation with actual in-app purchases, you will need to
register at least one test account on the Google Play Developer Console. You cannot use your
-developer account to test the complete in-app purchase process because Google Checkout does not let
+developer account to test the complete in-app purchase process because Google Wallet does not let
you buy items from yourself. If you have not set up test accounts before, see <a
href="{@docRoot}google/play/billing/billing_admin.html#billing-testing-setup">Setting up test
accounts</a>.</p>
@@ -208,8 +208,8 @@
<p>Also, a test account can purchase an item in your product list only if the item is published. The
application does not need to be published, but the item does need to be published.</p>
-<p>When you use a test account to purchase items, the test account is billed through Google Checkout
-and your Google Checkout Merchant account receives a payout for the purchase. Therefore, you may
+<p>When you use a test account to purchase items, the test account is billed through Google Wallet
+and your Google Wallet merchant account receives a payout for the purchase. Therefore, you may
want to refund purchases that are made with test accounts, otherwise the purchases will show up as
actual payouts to your merchant account.</p>
diff --git a/docs/html/google/play/billing/index.jd b/docs/html/google/play/billing/index.jd
index 44aa001..1969154 100644
--- a/docs/html/google/play/billing/index.jd
+++ b/docs/html/google/play/billing/index.jd
@@ -31,7 +31,7 @@
<p>Any application that you publish through Google Play can implement In-app Billing. No special
account or registration is required other than a Google Play Developer Console account and a Google
-Checkout merchant account.</p>
+Wallet merchant account.</p>
<p>To help you integrate in-app billing into your application, the Android SDK
provides a sample application that demonstrates how to sell standard in-app
diff --git a/docs/html/google/play/billing/v2/billing_integrate.jd b/docs/html/google/play/billing/v2/billing_integrate.jd
index 1581315..ca41e0b 100644
--- a/docs/html/google/play/billing/v2/billing_integrate.jd
+++ b/docs/html/google/play/billing/v2/billing_integrate.jd
@@ -226,7 +226,7 @@
List</a>.</p>
<p class="note"><strong>Note:</strong> You must publish the items in your product
list (<code>sword_001</code> and <code>potion_001</code>) even though you are not publishing the
- sample application. Also, you must have a Google Checkout Merchant account to add items to the
+ sample application. Also, you must have a Google Wallet merchant account to add items to the
sample application's product list.</p>
</li>
</ol>
@@ -239,7 +239,7 @@
<ol>
<li><strong>Make sure you have at least one test account registered under your Google Play
publisher account.</strong>
- <p>You cannot purchase items from yourself (Google Checkout prohibits this), so you need to
+ <p>You cannot purchase items from yourself (Google Wallet prohibits this), so you need to
create at least one test account that you can use to purchase items in the sample application.
To learn how to set up a test account, see <a
href="{@docRoot}google/play/billing/billing_testing.html#billing-testing-setup">Setting up Test
@@ -278,7 +278,7 @@
</li>
<li><strong>Run the application and purchase the sword or the potion.</strong>
<p>When you use a test account to purchase items, the test account is billed through Google
- Wallet and your Google Checkout Merchant account receives a payout for the purchase.
+ Wallet and your Google Wallet merchant account receives a payout for the purchase.
Therefore, you may want to refund purchases that are made with test accounts, otherwise the
purchases will show up as actual payouts to your merchant account.</p>
</ol>
diff --git a/docs/html/google/play/billing/v2/billing_subscriptions.jd b/docs/html/google/play/billing/v2/billing_subscriptions.jd
index 3bcf212..db18a53 100644
--- a/docs/html/google/play/billing/v2/billing_subscriptions.jd
+++ b/docs/html/google/play/billing/v2/billing_subscriptions.jd
@@ -65,7 +65,7 @@
token, a string value that uniquely identifies (and associates) a user ID and a
subscription ID. Google Play generates the purchase token when the user
completes the purchase of a subscription product (and payment is approved by
-Google Checkout) and then sends it to the purchasing app on the device through the
+Google Wallet) and then sends it to the purchasing app on the device through the
In-app Billing API. </p>
<p>At the conclusion of a <code>PURCHASE_REQUEST</code> message flow, your app
diff --git a/docs/html/guide/topics/graphics/hardware-accel.jd b/docs/html/guide/topics/graphics/hardware-accel.jd
index 9859c28..8ba6676 100644
--- a/docs/html/guide/topics/graphics/hardware-accel.jd
+++ b/docs/html/guide/topics/graphics/hardware-accel.jd
@@ -47,35 +47,24 @@
</div>
</div>
- <p>Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline is designed to
- better support hardware acceleration. Hardware acceleration carries out all drawing operations
- that are performed on a {@link android.view.View}'s canvas using the GPU. Because of the
- increased resources required to enable hardware acceleration, your app will consume more RAM.</p>
+ <p>Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline supports hardware
+ acceleration, meaning that all drawing operations that are performed on a {@link
+ android.view.View}'s canvas use the GPU. Because of the increased resources required to enable
+ hardware acceleration, your app will consume more RAM.</p>
- <p>The easiest way to enable hardware acceleration is to turn it on
- globally for your entire application. If your application uses only standard views and {@link
- android.graphics.drawable.Drawable}s, turning it on globally should not cause any adverse
- drawing effects. However, because hardware acceleration is not supported for all of the 2D drawing
- operations, turning it on might affect some of your applications that use custom views or drawing
- calls. Problems usually manifest themselves as invisible elements, exceptions, or wrongly
- rendered pixels. To remedy this, Android gives you the option to enable or disable hardware
- acceleration at the following levels:</p>
+ <p>Hardware acceleration is enabled by default if your Target API level is >=14, but can also
+ be explicitly enabled. If your application uses only standard views and {@link
+ android.graphics.drawable.Drawable}s, turning it on globally should not cause any adverse drawing
+ effects. However, because hardware acceleration is not supported for all of the 2D drawing
+ operations, turning it on might affect some of your custom views or drawing calls. Problems
+ usually manifest themselves as invisible elements, exceptions, or wrongly rendered pixels. To
+ remedy this, Android gives you the option to enable or disable hardware acceleration at multiple
+ levels. See <a href="#controlling">Controlling Hardware Acceleration</a>.</p>
- <ul>
- <li>Application</li>
-
- <li>Activity</li>
-
- <li>Window</li>
-
- <li>View</li>
- </ul>
-
- <p>If your application performs custom drawing, test your application on actual hardware
-devices with hardware acceleration turned on to find any problems. The <a
-href="#drawing-support">Unsupported drawing operations</a> section describes known issues with
-drawing operations that cannot be hardware accelerated and how to work around them.</p>
-
+ <p>If your application performs custom drawing, test your application on actual hardware devices
+ with hardware acceleration turned on to find any problems. The <a
+ href="#drawing-support">Unsupported drawing operations</a> section describes known issues with
+ hardware acceleration and how to work around them.</p>
<h2 id="controlling">Controlling Hardware Acceleration</h2>
<p>You can control hardware acceleration at the following levels:</p>
@@ -100,12 +89,12 @@
</pre>
<h4>Activity level</h4>
- <p>If your application does not behave properly with hardware acceleration turned on globally,
- you can control it for individual activities as well. To enable or disable hardware acceleration
- at the activity level, you can use the <code>android:hardwareAccelerated</code>
- attribute for the <a href="{@docRoot}guide/topics/manifest/activity-element.html">
- <code><activity></code></a> element. The following example enables hardware acceleration
-for the entire application but disables it for one activity:</p>
+ <p>If your application does not behave properly with hardware acceleration turned on globally, you
+ can control it for individual activities as well. To enable or disable hardware acceleration at
+ the activity level, you can use the <code>android:hardwareAccelerated</code> attribute for
+ the <a href="{@docRoot}guide/topics/manifest/activity-element.html">
+ <code><activity></code></a> element. The following example enables hardware acceleration for
+ the entire application but disables it for one activity:</p>
<pre>
<application android:hardwareAccelerated="true">
@@ -228,8 +217,7 @@
<p>With this model, you cannot rely on a view intersecting the dirty region to have its {@link
android.view.View#draw draw()} method executed. To ensure that the Android system records a
view’s display list, you must call {@link android.view.View#invalidate invalidate()}. Forgetting
- to do so causes a view to look the same even after changing it, which is an easier bug to find if
- it happens.</p>
+ to do so causes a view to look the same even after it has been changed.</p>
<p>Using display lists also benefits animation performance because setting specific properties,
such as alpha or rotation, does not require invalidating the targeted view (it is done
@@ -275,7 +263,7 @@
<p>The following table describes the support level of various operations across API levels:</p>
<style type="text/css">
- .tblGenFixed,.tblGeneric{font-size:15px}.tblGenFixed td {padding:0 3px;letter-spacing:0;word-spacing:0;background-color:#fff;z-index:1;border-top:0px none;border-left:0px none;border-bottom:1px solid #CCC;border-right:1px solid #CCC;} .dn {display:none} .tblGenFixed td.s0 {background-color:white;border-top:1px solid #CCC;border-left:1px solid #CCC;} .tblGenFixed td.s2 {background-color:#d9d9d9;color:#000000;text-align:center;} .tblGenFixed td.s1 {background-color:#434343;color:#ffffff;text-align:center;border-top:1px solid #CCC;} .tblGenFixed td.s9 {background-color:;color:#6aa84f;text-align:center;} .tblGenFixed td.s12 {background-color:white;color:#6aa84f;text-align:center;} .tblGenFixed td.s13 {background-color:#d9d9d9;color:#6aa84f;text-align:center;} .tblGenFixed td.s7 {background-color:#d9d9d9;color:#980000;text-align:center;} .tblGenFixed td.s8 {background-color:;color:#980000;text-align:center;} .tblGenFixed td.s5 {background-color:#434343;color:#ffffff;text-align:left;border-left:1px solid #CCC;} .tblGenFixed td.s6 {background-color:;font-family:courier new,monospace;color:;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.s10 {background-color:white;font-family:courier new,monospace;color:#000000;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.s3 {background-color:white;color:#000000;text-align:center;} .tblGenFixed td.s11 {background-color:white;color:#980000;text-align:center;} .tblGenFixed td.s4 {background-color:#d9d9d9;color:#000000;text-align:center;}
+ .tblGenFixed, .tblGeneric{font-size:15px}.tblGenFixed td {padding:0 3px;letter-spacing:0;word-spacing:0;background-color:#fff;z-index:1;border-top:0px none;border-left:0px none;border-bottom:1px solid #CCC;border-right:1px solid #CCC;} .dn {display:none} .tblGenFixed td.s0 {background-color:white;border-top:1px solid #CCC;border-left:1px solid #CCC;} .tblGenFixed td.s1 {background-color:#434343;color:#ffffff;text-align:center;border-top:1px solid #CCC;} .tblGenFixed td.s2 {background-color:#d9d9d9;color:#000000;text-align:center;} .tblGenFixed td.s3 {background-color:white;color:#000000;text-align:center;} .tblGenFixed td.s5 {background-color:#434343;color:#ffffff;text-align:left;border-left:1px solid #CCC;} .tblGenFixed td.s10 {background-color:white;font-family:courier new,monospace;color:#000000;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.g_pos {background-color:#d9d9d9;color:#6aa84f;text-align:center;} .tblGenFixed td.g_neg {background-color:#d9d9d9;color:#980000;text-align:center;} .tblGenFixed td.w_pos {background-color:white;color:#6aa84f;text-align:center;} .tblGenFixed td.w_neg {background-color:white;color:#980000;text-align:center;}
</style>
<table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain">
<tbody>
@@ -294,242 +282,329 @@
<td style="display:none;"></td>
<td class="s2">< 16</td>
<td class="s3">16</td>
- <td class="s4">17</td>
+ <td class="s2">17</td>
<td class="s3">18</td>
</tr>
<tr>
<td colspan="5" class="s5">Canvas</td>
</tr>
<tr>
- <td class="s6">clipPath()</td>
- <td class="s7">✗</td>
- <td class="s8">✗</td>
- <td class="s7">✗</td>
- <td class="s9">✓</td>
- </tr>
- <tr>
- <td class="s10">clipRegion()</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
- </tr>
- <tr>
- <td class="s10">clipRect(Region.Op.XOR)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
- </tr>
- <tr>
- <td class="s10">clipRect(Region.Op.Difference)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
- </tr>
- <tr>
- <td class="s10">clipRect(Region.Op.ReverseDifference)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
- </tr>
- <tr>
<td class="s10">drawBitmapMesh() (colors array)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
</tr>
<tr>
<td class="s10">drawPicture()</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">drawPosText()</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
- <td class="s13">✓</td>
- <td class="s12">✓</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ <td class="g_pos">✓</td>
+ <td class="w_pos">✓</td>
</tr>
<tr>
<td class="s10">drawTextOnPath()</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
- <td class="s13">✓</td>
- <td class="s12">✓</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ <td class="g_pos">✓</td>
+ <td class="w_pos">✓</td>
</tr>
<tr>
<td class="s10">drawVertices()</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">setDrawFilter()</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
- <td class="s13">✓</td>
- <td class="s12">✓</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ <td class="g_pos">✓</td>
+ <td class="w_pos">✓</td>
+ </tr>
+ <tr>
+ <td class="s10">clipPath()</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ </tr>
+ <tr>
+ <td class="s10">clipRegion()</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ </tr>
+ <tr>
+ <td class="s10">clipRect(Region.Op.XOR)</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ </tr>
+ <tr>
+ <td class="s10">clipRect(Region.Op.Difference)</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ </tr>
+ <tr>
+ <td class="s10">clipRect(Region.Op.ReverseDifference)</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ </tr>
+ <tr>
+ <td class="s10">clipRect() with rotation/perspective</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
</tr>
<tr>
<td colspan="5" class="s5">Paint</td>
</tr>
<tr>
- <td class="s6">setAntiAlias() (for text)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
+ <td class="s10">setAntiAlias() (for text)</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
</tr>
<tr>
- <td class="s6">setAntiAlias() (for lines)</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
- <td class="s13">✓</td>
- <td class="s12">✓</td>
+ <td class="s10">setAntiAlias() (for lines)</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ <td class="g_pos">✓</td>
+ <td class="w_pos">✓</td>
</tr>
<tr>
- <td class="s6">setFilterBitmap()</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s13">✓</td>
- <td class="s12">✓</td>
+ <td class="s10">setFilterBitmap()</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_pos">✓</td>
+ <td class="w_pos">✓</td>
</tr>
<tr>
- <td class="s6">setLinearText()</td>
- <td class="s7">✗</td>
- <td class="s8">✗</td>
- <td class="s7">✗</td>
- <td class="s8">✗</td>
+ <td class="s10">setLinearText()</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">setMaskFilter()</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">setPathEffect() (for lines)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">setRasterizer()</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">setShadowLayer() (other than text)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">setStrokeCap() (for lines)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s12">✓</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
</tr>
<tr>
<td class="s10">setStrokeCap() (for points)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">setSubpixelText()</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td colspan="5" class="s5">Xfermode</td>
</tr>
<tr>
- <td class="s6">AvoidXfermode</td>
- <td class="s7">✗</td>
- <td class="s8">✗</td>
- <td class="s7">✗</td>
- <td class="s8">✗</td>
+ <td class="s10">AvoidXfermode</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">PixelXorXfermode</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">PorterDuff.Mode.DARKEN (framebuffer)</td>
- <td class="s7">✗</td>
- <td class="s8">✗</td>
- <td class="s7">✗</td>
- <td class="s8">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">PorterDuff.Mode.LIGHTEN (framebuffer)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">PorterDuff.Mode.OVERLAY (framebuffer)</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td colspan="5" class="s5">Shader</td>
</tr>
<tr>
<td class="s10">ComposeShader inside ComposeShader</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">Same type shaders inside ComposeShader</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
</tr>
<tr>
<td class="s10">Local matrix on ComposeShader</td>
- <td class="s7">✗</td>
- <td class="s11">✗</td>
- <td class="s7">✗</td>
- <td class="s11">✓</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
</tr>
</tbody>
</table>
+ <h3 id="scaling">Canvas Scaling</h3>
+
+ <p>The hardware accelerated 2D rendering pipeline was built first to support unscaled drawing,
+ with some drawing operations degrading quality significantly at higher scale values. These
+ operations are implemented as textures drawn at scale 1.0, transformed by the GPU. In API level
+ <17, using these operations will result in scaling artifacts increasing with scale.</p>
+
+ The following table shows when implementation was changed to correctly handle large scales:
+
+ <table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain">
+ <tbody>
+ <tr class="rShim">
+ <td class="rShim" style="width:380px;"></td>
+ <td class="rShim" style="width:120px;"></td>
+ <td class="rShim" style="width:120px;"></td>
+ <td class="rShim" style="width:120px;"></td>
+ </tr>
+ <tr>
+ <td rowspan="2" class="s0"></td>
+ <td colspan="4" class="s1">API level</td>
+ </tr>
+ <tr>
+ <td style="display:none;"></td>
+ <td class="s2">< 17</td>
+ <td class="s3">17</td>
+ <td class="s2">18</td>
+ </tr>
+ <tr>
+ <td colspan="5" class="s5">Support for large scale factors</td>
+ </tr>
+ <tr>
+ <td class="s10">drawText()</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_pos">✓</td>
+ </tr>
+ <tr>
+ <td class="s10">drawPosText()</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ </tr>
+ <tr>
+ <td class="s10">drawTextOnPath()</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ </tr>
+ <tr>
+ <td class="s10">Simple Shapes*</td>
+ <td class="g_neg">✗</td>
+ <td class="w_pos">✓</td>
+ <td class="g_pos">✓</td>
+ </tr>
+ <tr>
+ <td class="s10">Complex Shapes*</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ </tr>
+ <tr>
+ <td class="s10">drawPath()</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ </tr>
+ <tr>
+ <td class="s10">Shadow layer</td>
+ <td class="g_neg">✗</td>
+ <td class="w_neg">✗</td>
+ <td class="g_neg">✗</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p class="note"><strong>Note</strong>: 'Simple' shapes are <code>drawRect()</code>,
+ <code>drawCircle()</code>, <code>drawOval()</code>, <code>drawRoundRect()</code>, and
+ <code>drawArc()</code> (with useCenter=false) commands issued with a Paint that doesn't have a
+ PathEffect, and doesn't contain non-default joins (via <code>setStrokeJoin()</code> /
+ <code>setStrokeMiter()</code>). Other instances of those draw commands fall under 'Complex,' in
+ the above chart.</p>
+
<p>If your application is affected by any of these missing features or limitations, you can turn
- off hardware acceleration for just the affected portion of your application by calling
- {@link android.view.View#setLayerType setLayerType(View.LAYER_TYPE_SOFTWARE, null)}. This way,
-you can still take advantage of hardware acceleratin everywhere else. See <a
-href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable and
-disable hardware acceleration at different levels in your application.
-
-
+ off hardware acceleration for just the affected portion of your application by calling {@link
+ android.view.View#setLayerType setLayerType(View.LAYER_TYPE_SOFTWARE, null)}. This way, you can
+ still take advantage of hardware acceleration everywhere else. See <a
+ href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable
+ and disable hardware acceleration at different levels in your application.
<h2 id="layers">View Layers</h2>
diff --git a/docs/html/tools/workflow/publishing/publishing.jd b/docs/html/tools/workflow/publishing/publishing.jd
index 649e80d..ab6321c 100644
--- a/docs/html/tools/workflow/publishing/publishing.jd
+++ b/docs/html/tools/workflow/publishing/publishing.jd
@@ -83,7 +83,7 @@
Developer Distribution Agreement</a>. After you register you can access the Developer
Console, where you can upload applications, configure publishing options, and monitor publishing
data. If you want to sell your applications or use the in-app billing feature, you will also need
-to set up a Google Checkout merchant account. For more information about the registration process,
+to set up a Google Wallet merchant account. For more information about the registration process,
see <a href="https://support.google.com/androidmarket/developer/bin/answer.py?hl=en&answer=113468">
Developer Registration</a>.</p>
@@ -271,7 +271,7 @@
<p>Any application that you publish through Google Play can implement in-app billing. No special
account or registration is required other than a Google Play publisher account and a Google
-Checkout Merchant account. Also, because the service uses no dedicated framework APIs, you can add
+Wallet merchant account. Also, because the service uses no dedicated framework APIs, you can add
in-app billing to any application that uses a minimum API level of 4 or higher.</p>
<p>To help you integrate in-app billing into your application, the Android SDK provides a <a
diff --git a/docs/html/training/in-app-billing/preparing-iab-app.jd b/docs/html/training/in-app-billing/preparing-iab-app.jd
index de2dac5..4698cf7 100644
--- a/docs/html/training/in-app-billing/preparing-iab-app.jd
+++ b/docs/html/training/in-app-billing/preparing-iab-app.jd
@@ -47,7 +47,7 @@
<p>The Google Play Developer Console is where you publish your In-app Billing application and manage the various digital goods that are available for purchase from your application. When you create a new application entry in the Developer Console, it automatically generates a public license key for your application. You will need this key to establish a trusted connection from your application to the Google Play servers. You only need to generate this key once per application, and don’t need to repeat these steps when you update the APK file for your application.</p>
<p>To add your application to the Developer Console:</p>
<ol>
-<li>Go to the <a href="http://play.google.com/apps/publish">Google Play Developer Console</a> site and log in. You will need to register for a new developer account, if you have not registered previously. To sell in-app items, you also need to have a <a href="http://www.google.com/wallet/merchants.html">Google Checkout Merchant</a> account.</li>
+<li>Go to the <a href="http://play.google.com/apps/publish">Google Play Developer Console</a> site and log in. You will need to register for a new developer account, if you have not registered previously. To sell in-app items, you also need to have a <a href="http://www.google.com/wallet/merchants.html">Google Wallet</a> merchant account.</li>
<li>Click on <strong>Try the new design</strong> to access the preview version of the Developer Console, if you are not already logged on to that version. </li>
<li>In the <strong>All Applications</strong> tab, add a new application entry.
<ol type="a">
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 01625dd..c2f4a2c 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -544,7 +544,7 @@
mTethering.getTetherableBluetoothRegexs().length != 0) &&
mTethering.getUpstreamIfaceTypes().length != 0);
- mVpn = new Vpn(mContext, mVpnCallback, mNetd);
+ mVpn = new Vpn(mContext, mVpnCallback, mNetd, this);
mVpn.startMonitoring(mContext, mTrackerHandler);
mClat = new Nat464Xlat(mContext, mNetd, this, mTrackerHandler);
@@ -3448,4 +3448,19 @@
mNetTrackers[networkType].supplyMessenger(messenger);
}
}
+
+ public int findConnectionTypeForIface(String iface) {
+ enforceConnectivityInternalPermission();
+
+ if (TextUtils.isEmpty(iface)) return ConnectivityManager.TYPE_NONE;
+ for (NetworkStateTracker tracker : mNetTrackers) {
+ if (tracker != null) {
+ LinkProperties lp = tracker.getLinkProperties();
+ if (lp != null && iface.equals(lp.getInterfaceName())) {
+ return tracker.getNetworkInfo().getType();
+ }
+ }
+ }
+ return ConnectivityManager.TYPE_NONE;
+ }
}
diff --git a/services/java/com/android/server/am/NativeCrashListener.java b/services/java/com/android/server/am/NativeCrashListener.java
index de439d7..a9454bd 100644
--- a/services/java/com/android/server/am/NativeCrashListener.java
+++ b/services/java/com/android/server/am/NativeCrashListener.java
@@ -219,6 +219,14 @@
pr = mAm.mPidsSelfLocked.get(pid);
}
if (pr != null) {
+ // Don't attempt crash reporting for persistent apps
+ if (pr.persistent) {
+ if (DEBUG) {
+ Slog.v(TAG, "Skipping report for persistent app " + pr);
+ }
+ return;
+ }
+
int bytes;
do {
// get some data
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 533db46..10c7e27 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -21,9 +21,11 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -33,6 +35,7 @@
import android.graphics.drawable.Drawable;
import android.net.BaseNetworkStateTracker;
import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.LinkProperties;
import android.net.LocalSocket;
@@ -71,6 +74,7 @@
import java.net.InetAddress;
import java.nio.charset.Charsets;
import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
import libcore.io.IoUtils;
@@ -92,12 +96,15 @@
private LegacyVpnRunner mLegacyVpnRunner;
private PendingIntent mStatusIntent;
private boolean mEnableNotif = true;
+ private final IConnectivityManager mConnService;
- public Vpn(Context context, VpnCallback callback, INetworkManagementService netService) {
+ public Vpn(Context context, VpnCallback callback, INetworkManagementService netService,
+ IConnectivityManager connService) {
// TODO: create dedicated TYPE_VPN network type
super(ConnectivityManager.TYPE_DUMMY);
mContext = context;
mCallback = callback;
+ mConnService = connService;
try {
netService.registerObserver(mObserver);
@@ -562,7 +569,6 @@
if (!profile.searchDomains.isEmpty()) {
config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
}
-
startLegacyVpn(config, racoon, mtpd);
}
@@ -630,9 +636,32 @@
private final String[][] mArguments;
private final LocalSocket[] mSockets;
private final String mOuterInterface;
+ private final AtomicInteger mOuterConnection =
+ new AtomicInteger(ConnectivityManager.TYPE_NONE);
private long mTimer = -1;
+ /**
+ * Watch for the outer connection (passing in the constructor) going away.
+ */
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
+ ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) {
+ NetworkInfo info = (NetworkInfo)intent.getExtra(
+ ConnectivityManager.EXTRA_NETWORK_INFO);
+ if (info != null && !info.isConnectedOrConnecting()) {
+ try {
+ mObserver.interfaceStatusChanged(mOuterInterface, false);
+ } catch (RemoteException e) {}
+ }
+ }
+ }
+ }
+ };
+
public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
super(TAG);
mConfig = config;
@@ -644,7 +673,22 @@
// This is the interface which VPN is running on,
// mConfig.interfaze will change to point to OUR
// internal interface soon. TODO - add inner/outer to mconfig
+ // TODO - we have a race - if the outer iface goes away/disconnects before we hit this
+ // we will leave the VPN up. We should check that it's still there/connected after
+ // registering
mOuterInterface = mConfig.interfaze;
+
+ try {
+ mOuterConnection.set(
+ mConnService.findConnectionTypeForIface(mOuterInterface));
+ } catch (Exception e) {
+ mOuterConnection.set(ConnectivityManager.TYPE_NONE);
+ }
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ mContext.registerReceiver(mBroadcastReceiver, filter);
+
}
public void check(String interfaze) {
@@ -661,6 +705,9 @@
IoUtils.closeQuietly(socket);
}
updateState(DetailedState.DISCONNECTED, "exit");
+ try {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ } catch (IllegalArgumentException e) {}
}
@Override