Merge "ChooserActivity: Cannot start app that the icon overflows the layout" into nyc-mr1-dev
diff --git a/docs/html/distribute/engage/easy-signin.jd b/docs/html/distribute/engage/easy-signin.jd
index 924c5b4..5c04064 100644
--- a/docs/html/distribute/engage/easy-signin.jd
+++ b/docs/html/distribute/engage/easy-signin.jd
@@ -1,70 +1,66 @@
-page.title=Add Quick and Secure Google Sign-in
+page.title=Add Quick and Secure Google Sign-In
page.metaDescription=Increase conversion rates while helping users minimize typing by letting users sign in with Google+.
page.tags="google", "identity", "signin"
page.image=images/cards/google-sign-in_2x.png
@jd:body
-<p>Get people into your apps quickly and securely, using a registration system they
-already use and trust – their Google account. With minimal effort, you can increase
-registration and sign-in conversion by adding trusted registration system that's
-familiar to users, consistent across devices, and quick and easy to use.</p>
-
-<p>Get started <a href="https://developers.google.com/identity/sign-in/">integrating
-Google sign-in into your apps and games</a>.</p>
-
-<div class="wrap">
- <div class="cols" style="margin-top:2em;">
- <div class="col-3of12">
- <h3>Quick and secure app access</h3>
- <p>A secure authentication system that makes sign-in easy for your users by
- letting them use their Google account, which they already use with Gmail,
- Play, Google+, and other Google services.</p>
- </div>
- <div class="col-8of12 col-push-1of12">
- <img src="{@docRoot}images/distribute/signin-secure.png" style="padding-top:1em;">
- </div>
- </div>
-
- <div class="cols" style="margin-top:2em;">
- <div class="col-3of12">
- <h3>Seamless experience across screens</h3>
- <p>Keep your users engaged, no matter what device they pick up or sit down at.
- Offer a seamless app experience across devices and into your website, securely
- from a one-time consent. </p>
- </div>
- <div class="col-8of12 col-push-1of12">
- <img src="{@docRoot}images/distribute/signin-seamless.png" style="padding-top:1em;">
- </div>
- </div>
-
- <div class="cols" style="margin-top:2em;">
- <div class="col-3of12">
- <h3>Help your users take action with Google</h3>
- <p>Securely connect users with Google services and let them pay with Google
- Wallet, share with Google contacts, save files to Drive, add events to
- Calendar, and more.</p>
- </div>
- <div class="col-8of12 col-push-1of12">
- <img src="{@docRoot}images/distribute/signin-apps.png" style="padding-top:1em;">
- </div>
- </div>
+<div class="figure">
+ <img src="{@docRoot}images/distribute/google-sign-in-banner.png" style="width:512px;">
</div>
+<p>
+ Get customers into your apps quickly and securely using a registration system that they
+ already use and trust – their Google account. With minimal effort, you can increase
+ registration and sign-in conversion by adding a trusted registration system that's familiar
+ to users, consistent across devices, and quick and easy to use.
+</p>
+<h2 id="tips">Benefits</h2>
-<h2>Tips</h2>
+<p>These are some of the ways Sign-In can improve your app:</p>
<ul>
-<li>Add <strong>over-the-air installs</strong> to your website. After signing in with Google
- on the web, users will have the option to send your Android app to their device instantly,
- without them ever leaving your website.</li>
- <li>With Google sign-in, you can take advantage of other <strong>Google+ platform
- features</strong> like adding a +1 button so users can make recommendations and the ability
- to share rich content to the Google+ stream.</li>
+ <li>
+ <strong>Quick and secure app access</strong>: Google Sign-In is a secure authentication
+ system that makes sign-in easy for your users by letting them use their Google account,
+ which they already use with Gmail, Google Play, Google+, and other Google services.
+ </li>
+
+ <li>
+ <strong>Seamless experience across screens</strong>: Keep your users engaged, no matter
+ what device they choose. Offer a secure and seamless app experience across devices and
+ into your website, from a one-time consent.
+ </li>
+
+ <li>
+ <strong>Convenient access to Google services</strong>: Securely connect users with
+ Google services and let them pay with Google Wallet, share with Google Contacts, save files
+ to Google Drive, and add events to Google Calendar.
+ </li>
</ul>
+<p>Get started integrating<a href="https://developers.google.com/identity/sign-in/">
+Google Sign-In</a> into your apps and games.</p>
-<h2 style="clear:both" id="related-resources">Related Resources</h2>
+<h2 id="tips">Tips</h2>
+
+<p>Here are some suggestions for enhancing the Sign-In user experience:</p>
+
+<ul>
+ <li>
+ Add <strong>over-the-air installs</strong> to your website. After signing in with Google
+ on the web, users have the option to send your Android app to their device instantly,
+ without ever leaving your website.
+ </li>
+
+ <li>
+ With Google Sign-In, you can take advantage of other <strong>Google+ platform
+ features</strong>, like adding a +1 button so users can make recommendations and have
+ the ability to share rich content to their Google+ streams.
+ </li>
+</ul>
+
+<h2 style="clear:both" id="related-resources">Related resources</h2>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/engage/gplus"
@@ -72,5 +68,3 @@
data-cardsizes="9x3"
data-maxresults="4">
</div>
-
-
diff --git a/docs/html/images/distribute/google-sign-in-banner.png b/docs/html/images/distribute/google-sign-in-banner.png
new file mode 100644
index 0000000..ba04686
--- /dev/null
+++ b/docs/html/images/distribute/google-sign-in-banner.png
Binary files differ
diff --git a/docs/html/jd_extras_en.js b/docs/html/jd_extras_en.js
index 15485c4..5c42277 100644
--- a/docs/html/jd_extras_en.js
+++ b/docs/html/jd_extras_en.js
@@ -2982,7 +2982,7 @@
"url": "https://developers.google.com/identity/sign-in/android/people",
"timestamp": 1383243492000,
"image": "images/cards/google-sign-in_2x.png",
- "title": "Get user profile details",
+ "title": "Get User Profile Details",
"summary": "After users sign-in with Google, you can access their age range, language, and public profile information.",
"keywords": ["signin", "identity", "google"],
"type": "distribute",
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index 8c20ddc..f36c00c 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -228,7 +228,7 @@
if (exportResult.resultCode != KeyStore.NO_ERROR) {
throw (UnrecoverableKeyException)
new UnrecoverableKeyException("Failed to obtain X.509 form of public key")
- .initCause(KeyStore.getKeyStoreException(errorCode));
+ .initCause(KeyStore.getKeyStoreException(exportResult.resultCode));
}
final byte[] x509EncodedPublicKey = exportResult.exportData;
diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml
index 3d6643d..5dfac95 100644
--- a/packages/Shell/res/values/strings.xml
+++ b/packages/Shell/res/values/strings.xml
@@ -25,8 +25,8 @@
<!-- Content notification indicating a bugreport is being updated before it can be shared, asking the user to wait [CHAR LIMIT=50] -->
<string name="bugreport_updating_wait">Please wait\u2026</string>
- <!-- Text of notification indicating that swipe left will share the captured bugreport. [CHAR LIMIT=100] -->
- <string name="bugreport_finished_text" product="watch">Swipe left to share your bug report</string>
+ <!-- Text of notification indicating that bugreport will appear on the phone. [CHAR LIMIT=100] -->
+ <string name="bugreport_finished_text" product="watch">The bug report will appear on the phone shortly</string>
<!-- Text of notification indicating that tapping will share the captured bugreport. [CHAR LIMIT=100] -->
<string name="bugreport_finished_text" product="default">Tap to share your bug report</string>
<!-- Text of notification indicating that swipe left will share the captured bugreport, but giving user the option to wait for the screenshot. [CHAR LIMIT=100] -->
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 6bc4df7..f04df4b 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -212,6 +212,8 @@
private static final Bundle sNotificationBundle = new Bundle();
+ private boolean mIsWatch;
+
@Override
public void onCreate() {
mContext = getApplicationContext();
@@ -225,6 +227,9 @@
Log.w(TAG, "Could not create directory " + mScreenshotsDir);
}
}
+ final Configuration conf = mContext.getResources().getConfiguration();
+ mIsWatch = (conf.uiMode & Configuration.UI_MODE_TYPE_MASK) ==
+ Configuration.UI_MODE_TYPE_WATCH;
}
@Override
@@ -439,56 +444,68 @@
return;
}
- final NumberFormat nf = NumberFormat.getPercentInstance();
- nf.setMinimumFractionDigits(2);
- nf.setMaximumFractionDigits(2);
- final String percentageText = nf.format((double) info.progress / info.max);
- final Action cancelAction = new Action.Builder(null, mContext.getString(
- com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
- final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
- infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH);
- infoIntent.putExtra(EXTRA_ID, info.id);
- final PendingIntent infoPendingIntent =
- PendingIntent.getService(mContext, info.id, infoIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- final Action infoAction = new Action.Builder(null,
- mContext.getString(R.string.bugreport_info_action),
- infoPendingIntent).build();
- final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class);
- screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT);
- screenshotIntent.putExtra(EXTRA_ID, info.id);
- PendingIntent screenshotPendingIntent = mTakingScreenshot ? null : PendingIntent
- .getService(mContext, info.id, screenshotIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- final Action screenshotAction = new Action.Builder(null,
- mContext.getString(R.string.bugreport_screenshot_action),
- screenshotPendingIntent).build();
-
- final String title = mContext.getString(R.string.bugreport_in_progress_title, info.id);
-
- final String name =
- info.name != null ? info.name : mContext.getString(R.string.bugreport_unnamed);
-
- final Notification notification = newBaseNotification(mContext)
- .setContentTitle(title)
- .setTicker(title)
- .setContentText(name)
- .setProgress(info.max, info.progress, false)
- .setOngoing(true)
- .setContentIntent(infoPendingIntent)
- .setActions(infoAction, screenshotAction, cancelAction)
- .build();
-
if (info.finished) {
Log.w(TAG, "Not sending progress notification because bugreport has finished already ("
+ info + ")");
return;
}
+
+ final NumberFormat nf = NumberFormat.getPercentInstance();
+ nf.setMinimumFractionDigits(2);
+ nf.setMaximumFractionDigits(2);
+ final String percentageText = nf.format((double) info.progress / info.max);
+
+ String title = mContext.getString(R.string.bugreport_in_progress_title, info.id);
+
+ // TODO: Remove this workaround when notification progress is implemented on Wear.
+ if (mIsWatch) {
+ nf.setMinimumFractionDigits(0);
+ nf.setMaximumFractionDigits(0);
+ final String watchPercentageText = nf.format((double) info.progress / info.max);
+ title = title + "\n" + watchPercentageText;
+ }
+
+ final String name =
+ info.name != null ? info.name : mContext.getString(R.string.bugreport_unnamed);
+
+ final Notification.Builder builder = newBaseNotification(mContext)
+ .setContentTitle(title)
+ .setTicker(title)
+ .setContentText(name)
+ .setProgress(info.max, info.progress, false)
+ .setOngoing(true);
+
+ // Wear bugreport doesn't need the bug info dialog, screenshot and cancel action.
+ if (!mIsWatch) {
+ final Action cancelAction = new Action.Builder(null, mContext.getString(
+ com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
+ final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
+ infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH);
+ infoIntent.putExtra(EXTRA_ID, info.id);
+ final PendingIntent infoPendingIntent =
+ PendingIntent.getService(mContext, info.id, infoIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ final Action infoAction = new Action.Builder(null,
+ mContext.getString(R.string.bugreport_info_action),
+ infoPendingIntent).build();
+ final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class);
+ screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT);
+ screenshotIntent.putExtra(EXTRA_ID, info.id);
+ PendingIntent screenshotPendingIntent = mTakingScreenshot ? null : PendingIntent
+ .getService(mContext, info.id, screenshotIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ final Action screenshotAction = new Action.Builder(null,
+ mContext.getString(R.string.bugreport_screenshot_action),
+ screenshotPendingIntent).build();
+ builder.setContentIntent(infoPendingIntent)
+ .setActions(infoAction, screenshotAction, cancelAction);
+ }
+
if (DEBUG) {
Log.d(TAG, "Sending 'Progress' notification for id " + info.id + " (pid " + info.pid
+ "): " + percentageText);
}
- sendForegroundabledNotification(info.id, notification);
+ sendForegroundabledNotification(info.id, builder.build());
}
private void sendForegroundabledNotification(int id, Notification notification) {
@@ -854,10 +871,7 @@
// Stop running on foreground, otherwise share notification cannot be dismissed.
stopForegroundWhenDone(id);
- final Configuration conf = mContext.getResources().getConfiguration();
- if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
- triggerLocalNotification(mContext, info);
- }
+ triggerLocalNotification(mContext, info);
}
/**
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 05207b9..402d9ad 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -16,17 +16,21 @@
package com.android.wallpaperbackup;
+import static android.app.WallpaperManager.FLAG_LOCK;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+
import android.app.WallpaperManager;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.FullBackupDataOutput;
import android.content.Context;
+import android.content.SharedPreferences;
import android.graphics.Rect;
import android.os.Environment;
+import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
-import android.system.Os;
import android.util.Slog;
import android.util.Xml;
@@ -40,7 +44,7 @@
public class WallpaperBackupAgent extends BackupAgent {
private static final String TAG = "WallpaperBackup";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
// NB: must be kept in sync with WallpaperManagerService but has no
// compile-time visibility.
@@ -57,6 +61,11 @@
static final String EMPTY_SENTINEL = "empty";
static final String QUOTA_SENTINEL = "quota";
+ // Not-for-backup bookkeeping
+ static final String PREFS_NAME = "wbprefs.xml";
+ static final String SYSTEM_GENERATION = "system_gen";
+ static final String LOCK_GENERATION = "lock_gen";
+
private File mWallpaperInfo; // wallpaper metadata file
private File mWallpaperFile; // primary wallpaper image file
private File mLockWallpaperFile; // lock wallpaper image file
@@ -106,27 +115,48 @@
// only back up the wallpaper if we've been told it's allowed
if (mWm.isWallpaperBackupEligible()) {
if (DEBUG) {
- Slog.v(TAG, "Wallpaper is backup-eligible; linking & writing");
+ Slog.v(TAG, "Wallpaper is backup-eligible");
}
- // In case of prior muddled state
- infoStage.delete();
- imageStage.delete();
- lockImageStage.delete();
+ SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+ final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1);
+ final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1);
+ final int sysGeneration =
+ mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM);
+ final int lockGeneration =
+ mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM);
+ final boolean sysChanged = (sysGeneration != lastSysGeneration);
+ final boolean lockChanged = (lockGeneration != lastLockGeneration);
+
+ if (DEBUG) {
+ Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged);
+ Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged);
+ }
if (mWallpaperInfo.exists()) {
- Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath());
+ if (sysChanged || lockChanged || !infoStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying");
+ FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage);
+ }
fullBackupFile(infoStage, data);
}
if (mWallpaperFile.exists()) {
- Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath());
+ if (sysChanged || !imageStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New system wallpaper; copying");
+ FileUtils.copyFileOrThrow(mWallpaperFile, imageStage);
+ }
fullBackupFile(imageStage, data);
+ prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
}
// Don't try to store the lock image if we overran our quota last time
if (mLockWallpaperFile.exists() && !mQuotaExceeded) {
- Os.link(mLockWallpaperFile.getCanonicalPath(), lockImageStage.getCanonicalPath());
+ if (lockChanged || !lockImageStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying");
+ FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage);
+ }
fullBackupFile(lockImageStage, data);
+ prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
}
} else {
if (DEBUG) {
@@ -136,13 +166,6 @@
} catch (Exception e) {
Slog.e(TAG, "Unable to back up wallpaper", e);
} finally {
- if (DEBUG) {
- Slog.v(TAG, "Removing backup stage links");
- }
- infoStage.delete();
- imageStage.delete();
- lockImageStage.delete();
-
// Even if this time we had to back off on attempting to store the lock image
// due to exceeding the data quota, try again next time. This will alternate
// between "try both" and "only store the primary image" until either there
@@ -189,26 +212,30 @@
Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
} finally {
if (DEBUG) {
- Slog.v(TAG, "Removing restore stage files");
+ Slog.v(TAG, "Restore finished; clearing backup bookkeeping");
}
infoStage.delete();
imageStage.delete();
lockImageStage.delete();
+
+ SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+ prefs.edit()
+ .putInt(SYSTEM_GENERATION, -1)
+ .putInt(LOCK_GENERATION, -1)
+ .commit();
}
}
private void restoreFromStage(File stage, File info, String hintTag, int which)
throws IOException {
if (stage.exists()) {
- if (DEBUG) {
- Slog.v(TAG, "Got restored wallpaper; applying which=" + which);
- }
// Parse the restored info file to find the crop hint. Note that this currently
// relies on a priori knowledge of the wallpaper info file schema.
Rect cropHint = parseCropHint(info, hintTag);
if (cropHint != null) {
+ Slog.i(TAG, "Got restored wallpaper; applying which=" + which);
if (DEBUG) {
- Slog.v(TAG, "Restored crop hint " + cropHint + "; now writing data");
+ Slog.v(TAG, "Restored crop hint " + cropHint);
}
try (FileInputStream in = new FileInputStream(stage)) {
mWm.setStream(in, cropHint, true, which);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 67ff085..d426dd0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13604,7 +13604,7 @@
sb.append("Process: ").append(processName).append("\n");
int flags = process.info.flags;
IPackageManager pm = AppGlobals.getPackageManager();
- sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
+ sb.append("Flags: 0x").append(Integer.toHexString(flags)).append("\n");
for (int ip=0; ip<process.pkgList.size(); ip++) {
String pkg = process.pkgList.keyAt(ip);
sb.append("Package: ").append(pkg);
diff --git a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
index 40ee5d8..7126cb5 100644
--- a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
+++ b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
@@ -215,7 +215,11 @@
*/
public ArraySet<ComponentName> getInstalled(int userId) {
synchronized (mLock) {
- return mInstalledSet.get(userId);
+ ArraySet<ComponentName> ret = mInstalledSet.get(userId);
+ if (ret == null) {
+ return new ArraySet<ComponentName>();
+ }
+ return ret;
}
}
@@ -227,7 +231,12 @@
*/
public ArraySet<ComponentName> getEnabled(int userId) {
synchronized (mLock) {
- return mEnabledSet.get(userId);
+ ArraySet<ComponentName> ret = mEnabledSet.get(userId);
+ if (ret == null) {
+ return new ArraySet<ComponentName>();
+ }
+ return ret;
+
}
}