diff options
18 files changed, 229 insertions, 101 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index ac5f3effa1f9..a5fcec622956 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -5952,7 +5952,7 @@ public class Activity extends ContextThemeWrapper return false; } try { - return ActivityManagerNative.getDefault().isTopOfTask(mToken); + return ActivityManagerNative.getDefault().isTopOfTask(getActivityToken()); } catch (RemoteException e) { return false; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 7198146bee0f..b220b2e23732 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1166,12 +1166,22 @@ public final class ActivityThread { @Override public void dumpDbInfo(final FileDescriptor fd, final String[] args) { if (mSystemThread) { - // Ensure this invocation is asynchronous to prevent - // writer waiting due to buffer cannot be consumed. + // Ensure this invocation is asynchronous to prevent writer waiting if buffer cannot + // be consumed. But it must duplicate the file descriptor first, since caller might + // be closing it. + final ParcelFileDescriptor dup; + try { + dup = ParcelFileDescriptor.dup(fd); + } catch (IOException e) { + Log.w(TAG, "Could not dup FD " + fd.getInt$()); + return; + } + AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { @Override public void run() { - dumpDatabaseInfo(fd, args); + dumpDatabaseInfo(dup.getFileDescriptor(), args); + IoUtils.closeQuietly(dup); } }); } else { diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java index 787202eded02..dc8e4b93e093 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -19,7 +19,6 @@ package android.text; import android.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Paint; -import android.text.style.ParagraphStyle; import android.util.Log; import com.android.internal.util.ArrayUtils; @@ -554,7 +553,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (adjustSelection) { boolean changed = false; if (selectionStart > start && selectionStart < end) { - final int offset = (selectionStart - start) * newLen / origLen; + final long diff = selectionStart - start; + final int offset = Math.toIntExact(diff * newLen / origLen); selectionStart = start + offset; changed = true; @@ -562,7 +562,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable Spanned.SPAN_POINT_POINT); } if (selectionEnd > start && selectionEnd < end) { - final int offset = (selectionEnd - start) * newLen / origLen; + final long diff = selectionEnd - start; + final int offset = Math.toIntExact(diff * newLen / origLen); selectionEnd = start + offset; changed = true; diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java index 52f35de7e189..d0d4507e7b62 100644 --- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java +++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java @@ -16,7 +16,6 @@ package android.view.accessibility; -import android.annotation.Nullable; import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; @@ -102,9 +101,8 @@ public final class AccessibilityWindowInfo implements Parcelable { /** * Gets the title of the window. * - * @return The title of the window, or {@code null} if none is available. + * @return The title. */ - @Nullable public CharSequence getTitle() { return mTitle; } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 9ad750d3a599..18408aa72f5f 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -528,22 +528,16 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public void setTitle(CharSequence title) { - setTitle(title, true); - } - - public void setTitle(CharSequence title, boolean updateAccessibilityTitle) { if (mTitleView != null) { mTitleView.setText(title); } else if (mDecorContentParent != null) { mDecorContentParent.setWindowTitle(title); } mTitle = title; - if (updateAccessibilityTitle) { - WindowManager.LayoutParams params = getAttributes(); - if (!TextUtils.equals(title, params.accessibilityTitle)) { - params.accessibilityTitle = TextUtils.stringOrSpannedString(title); - dispatchWindowAttributesChanged(getAttributes()); - } + WindowManager.LayoutParams params = getAttributes(); + if (!TextUtils.equals(title, params.accessibilityTitle)) { + params.accessibilityTitle = TextUtils.stringOrSpannedString(title); + dispatchWindowAttributesChanged(getAttributes()); } } diff --git a/core/java/com/android/internal/util/FastPrintWriter.java b/core/java/com/android/internal/util/FastPrintWriter.java index e46e6b026fd9..dc3832a1713d 100644 --- a/core/java/com/android/internal/util/FastPrintWriter.java +++ b/core/java/com/android/internal/util/FastPrintWriter.java @@ -345,7 +345,7 @@ public class FastPrintWriter extends PrintWriter { if (mOutputStream != null) { CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos); CoderResult result = mCharset.encode(charBuffer, mBytes, true); - while (true) { + while (!mIoError) { if (result.isError()) { throw new IOException(result.toString()); } else if (result.isOverflow()) { diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 1beea8c11386..2e0dfa5fa731 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -916,23 +916,6 @@ public class LockPatternUtils { } /** - * Gets whether the device is encrypted. - * - * @return Whether the device is encrypted. - */ - public static boolean isDeviceEncrypted() { - IMountService mountService = IMountService.Stub.asInterface( - ServiceManager.getService("mount")); - try { - return mountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE - && mountService.getPasswordType() != StorageManager.CRYPT_TYPE_DEFAULT; - } catch (RemoteException re) { - Log.e(TAG, "Error getting encryption state", re); - } - return true; - } - - /** * Determine if the device supports encryption, even if it's set to default. This * differs from isDeviceEncrypted() in that it returns true even if the device is * encrypted with the default password. diff --git a/docs/html/distribute/index.jd b/docs/html/distribute/index.jd index 638477302d0a..424983d4d286 100644 --- a/docs/html/distribute/index.jd +++ b/docs/html/distribute/index.jd @@ -67,7 +67,9 @@ page.metaDescription=The most visited store in the world for Android apps. Cloud </li> <li class="dac-tab-view" data-tab-view="type"> + <!-- <div class="dac-filter-item" data-filter-value="type:distribute" data-filter-name="Articles"></div> + --> <div class="dac-filter-item" data-filter-value="type:youtube" data-filter-name="Videos"></div> <div class="dac-filter-item" data-filter-value="type:blog" data-filter-name="Blog posts"></div> </li> @@ -78,7 +80,7 @@ page.metaDescription=The most visited store in the world for Android apps. Cloud </div> <div class="resource-flow-layout col-16" id="latest-resources" - data-query="type:distribute, type:youtube+tag:googleplay, type:blog+tag:googleplay+tag:featured" + data-query="type:youtube+tag:googleplay, type:blog+tag:googleplay+tag:featured" data-sortOrder="-timestamp" data-cardSizes="6x6" data-items-per-page="6" diff --git a/docs/html/preview/features/data-saver.jd b/docs/html/preview/features/data-saver.jd index 761556e1ead6..abc47eaa3837 100644 --- a/docs/html/preview/features/data-saver.jd +++ b/docs/html/preview/features/data-saver.jd @@ -179,10 +179,13 @@ if (connMgr.isActiveNetworkMetered()) { Testing with Android Debug Bridge Commands </h2> -The <a href="{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a> -provides a few commands that you can use to check and configure network -permissions: - +<p> + The <a href="{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a> + provides a few commands that you can use to test your app in Data Saver + conditions. You can check and configure network + permissions or set wireless networks as metered to test your app on unmetered + networks. +</p> <dl> <dt> <code>$ adb shell dumpsys netpolicy</code> @@ -231,4 +234,23 @@ permissions: Removes the specified package UID from the whitelist to block background metered data usage while Data Saver is enabled. </dd> + + <dt> + <code>$ adb shell cmd netpolicy list wifi-networks</code> + </dt> + + <dd> + Lists all wifi networks, displaying whether they're metered. + </dd> + + + <dt> + <code>$ adb shell cmd netpolicy set metered-network <WIFI_SSID> + true</code> + </dt> + + <dd> + Sets wifi with the specified SSID as metered, allowing you to simulate a + metered network on an unmetered network. + </dd> </dl>
\ No newline at end of file diff --git a/docs/html/preview/index.jd b/docs/html/preview/index.jd index b0631add8b13..918de48c41d3 100644 --- a/docs/html/preview/index.jd +++ b/docs/html/preview/index.jd @@ -57,7 +57,7 @@ footer.hide=1 <div id="useUpdatedTemplates" style="display:none" class="dac-section dac-slim dac-gray dac-expand"> <div class="wrap dac-offset-parent"> - <a class="dac-fab dac-scroll-button" data-scroll-button href="#build-apps"> + <a class="dac-fab dac-scroll-button" data-scroll-button href="#latest"> <i class="dac-sprite dac-arrow-down-gray"></i> </a> <ul class="dac-actions"> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 6a57c134d769..cd08f34aa6a5 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -580,7 +580,7 @@ <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Reducir datos está activada"</string> <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Reducir datos está desactivada"</string> <string name="switch_bar_on" msgid="1142437840752794229">"Activado"</string> - <string name="switch_bar_off" msgid="8803270596930432874">"Desactivar"</string> + <string name="switch_bar_off" msgid="8803270596930432874">"Desactivado"</string> <string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string> <string name="start" msgid="6873794757232879664">"Iniciar"</string> <string name="center" msgid="4327473927066010960">"Centro"</string> diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 6a0d48872a6b..acf8009e34a6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3388,7 +3388,6 @@ public class ConnectivityService extends IConnectivityManager.Stub * was no always-on VPN to start. {@code false} otherwise. */ private boolean startAlwaysOnVpn(int userId) { - final String alwaysOnPackage; synchronized (mVpns) { Vpn vpn = mVpns.get(userId); if (vpn == null) { @@ -3397,27 +3396,8 @@ public class ConnectivityService extends IConnectivityManager.Stub Slog.wtf(TAG, "User " + userId + " has no Vpn configuration"); return false; } - alwaysOnPackage = vpn.getAlwaysOnPackage(); - // Skip if there is no service to start. - if (alwaysOnPackage == null) { - return true; - } - // Skip if the service is already established. This isn't bulletproof: it's not bound - // until after establish(), so if it's mid-setup onStartCommand will be sent twice, - // which may restart the connection. - if (vpn.getNetworkInfo().isConnected()) { - return true; - } - } - // Start the VPN service declared in the app's manifest. - Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE); - serviceIntent.setPackage(alwaysOnPackage); - try { - return mContext.startServiceAsUser(serviceIntent, UserHandle.of(userId)) != null; - } catch (RuntimeException e) { - Slog.w(TAG, "VpnService " + serviceIntent + " failed to start", e); - return false; + return vpn.startAlwaysOnVpn(); } } @@ -3449,17 +3429,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } - // Save the configuration - final long token = Binder.clearCallingIdentity(); - try { - final ContentResolver cr = mContext.getContentResolver(); - Settings.Secure.putStringForUser(cr, Settings.Secure.ALWAYS_ON_VPN_APP, - packageName, userId); - Settings.Secure.putIntForUser(cr, Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, - (lockdown ? 1 : 0), userId); - } finally { - Binder.restoreCallingIdentity(token); - } + vpn.saveAlwaysOnPackage(); } return true; } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 4439a24a4b07..d83a750ccbb3 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -3764,7 +3764,8 @@ final class ActivityStack { r.finishLaunchTickingLocked(); } - private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) { + private void removeActivityFromHistoryLocked( + ActivityRecord r, TaskRecord oldTop, String reason) { mStackSupervisor.removeChildActivityContainers(r); finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null); r.makeFinishingLocked(); @@ -3783,10 +3784,11 @@ final class ActivityStack { validateAppTokensLocked(); } final TaskRecord task = r.task; + final TaskRecord topTask = oldTop != null ? oldTop : topTask(); if (task != null && task.removeActivity(r)) { if (DEBUG_STACK) Slog.i(TAG_STACK, "removeActivityFromHistoryLocked: last activity removed from " + this); - if (mStackSupervisor.isFocusedStack(this) && task == topTask() && + if (mStackSupervisor.isFocusedStack(this) && task == topTask && task.isOverHomeStack()) { mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason); } @@ -3922,6 +3924,12 @@ final class ActivityStack { boolean removedFromHistory = false; + // If the activity is finishing, it's no longer considered in topRunningActivityLocked, + // and cleanUpActivityLocked() may change focus to another activity (or task). + // Get the current top task now, as removeActivityFromHistoryLocked() below need this + // to decide whether to return to home stack after removal. + final TaskRecord topTask = topTask(); + cleanUpActivityLocked(r, false, false); final boolean hadApp = r.app != null; @@ -3956,7 +3964,8 @@ final class ActivityStack { // up. //Slog.w(TAG, "Exception thrown during finish", e); if (r.finishing) { - removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy"); + removeActivityFromHistoryLocked( + r, topTask, reason + " exceptionInScheduleDestroy"); removedFromHistory = true; skipDestroy = true; } @@ -3987,7 +3996,7 @@ final class ActivityStack { } else { // remove this record from the history. if (r.finishing) { - removeActivityFromHistoryLocked(r, reason + " hadNoApp"); + removeActivityFromHistoryLocked(r, topTask, reason + " hadNoApp"); removedFromHistory = true; } else { if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (no app)"); @@ -4018,7 +4027,7 @@ final class ActivityStack { if (isInStackLocked(r) != null) { if (r.state == ActivityState.DESTROYING) { cleanUpActivityLocked(r, true, false); - removeActivityFromHistoryLocked(r, reason); + removeActivityFromHistoryLocked(r, null, reason); } } mStackSupervisor.resumeFocusedStackTopActivityLocked(); @@ -4176,7 +4185,7 @@ final class ActivityStack { } cleanUpActivityLocked(r, true, true); if (remove) { - removeActivityFromHistoryLocked(r, "appDied"); + removeActivityFromHistoryLocked(r, null, "appDied"); } } } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 8932e4bbafc4..c84aaacd8aff 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -1537,6 +1537,11 @@ final class TaskRecord { ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; + // Always set fontScale to be euqal to global. Can't set to 0, as that makes the override + // config not equal to EMPTY. Also can't set to 1, as Configuration.updateFrom will use + // the override scale as long as it's non-zero, and we'll always use 1. + config.fontScale = serviceConfig.fontScale; + // For calculating screen layout, we need to use the non-decor inset screen area for the // calculation for compatibility reasons, i.e. screen area without system bars that could // never go away in Honeycomb. @@ -1564,6 +1569,7 @@ final class TaskRecord { extracted.smallestScreenWidthDp = config.smallestScreenWidthDp; extracted.orientation = config.orientation; extracted.screenLayout = config.screenLayout; + extracted.fontScale = config.fontScale; return extracted; } @@ -1597,6 +1603,9 @@ final class TaskRecord { newScreenLayout = (newScreenLayout & ~SCREENLAYOUT_SIZE_MASK) | (overrideScreenLayout & SCREENLAYOUT_SIZE_MASK); mOverrideConfig.screenLayout = newScreenLayout; + // we never override the fontScale, however we need to copy over the global value + // so that the default 1.0 doesn't get applied as an override. + mOverrideConfig.fontScale = globalConfig.fontScale; } static Rect validateBounds(Rect bounds) { diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 1bdb48a23d9d..ebacc71515bb 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -30,6 +30,7 @@ import android.app.AppOpsManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -53,6 +54,7 @@ import android.net.NetworkInfo.DetailedState; import android.net.NetworkMisc; import android.net.RouteInfo; import android.net.UidRange; +import android.net.Uri; import android.os.Binder; import android.os.FileUtils; import android.os.IBinder; @@ -60,12 +62,14 @@ import android.os.INetworkManagementService; import android.os.Looper; import android.os.Parcel; import android.os.ParcelFileDescriptor; +import android.os.PatternMatcher; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemService; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.security.Credentials; import android.security.KeyStore; import android.text.TextUtils; @@ -163,6 +167,45 @@ public class Vpn { // Handle of user initiating VPN. private final int mUserHandle; + // Listen to package remove and change event in this user + private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final Uri data = intent.getData(); + final String packageName = data == null ? null : data.getSchemeSpecificPart(); + if (packageName == null) { + return; + } + + synchronized (Vpn.this) { + // Avoid race that always-on package has been unset + if (!packageName.equals(getAlwaysOnPackage())) { + return; + } + + final String action = intent.getAction(); + Log.i(TAG, "Received broadcast " + action + " for always-on package " + packageName + + " in user " + mUserHandle); + + switch(action) { + case Intent.ACTION_PACKAGE_REPLACED: + // Start vpn after app upgrade + startAlwaysOnVpn(); + break; + case Intent.ACTION_PACKAGE_REMOVED: + final boolean isPackageRemoved = !intent.getBooleanExtra( + Intent.EXTRA_REPLACING, false); + if (isPackageRemoved) { + setAndSaveAlwaysOnPackage(null, false); + } + break; + } + } + } + }; + + private boolean mIsPackageIntentReceiverRegistered = false; + public Vpn(Looper looper, Context context, INetworkManagementService netService, int userHandle) { mContext = context; @@ -233,10 +276,37 @@ public class Vpn { mAlwaysOn = (packageName != null); mLockdown = (mAlwaysOn && lockdown); + maybeRegisterPackageChangeReceiverLocked(packageName); setVpnForcedLocked(mLockdown); return true; } + private void unregisterPackageChangeReceiverLocked() { + // register previous intent filter + if (mIsPackageIntentReceiverRegistered) { + mContext.unregisterReceiver(mPackageIntentReceiver); + mIsPackageIntentReceiverRegistered = false; + } + } + + private void maybeRegisterPackageChangeReceiverLocked(String packageName) { + // Unregister IntentFilter listening for previous always-on package change + unregisterPackageChangeReceiverLocked(); + + if (packageName != null) { + mIsPackageIntentReceiverRegistered = true; + + IntentFilter intentFilter = new IntentFilter(); + // Protected intent can only be sent by system. No permission required in register. + intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); + intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); + intentFilter.addDataScheme("package"); + intentFilter.addDataSchemeSpecificPart(packageName, PatternMatcher.PATTERN_LITERAL); + mContext.registerReceiverAsUser( + mPackageIntentReceiver, UserHandle.of(mUserHandle), intentFilter, null, null); + } + } + /** * @return the package name of the VPN controller responsible for always-on VPN, * or {@code null} if none is set or always-on VPN is controlled through @@ -249,6 +319,69 @@ public class Vpn { } /** + * Save the always-on package and lockdown config into Settings.Secure + */ + public synchronized void saveAlwaysOnPackage() { + final long token = Binder.clearCallingIdentity(); + try { + final ContentResolver cr = mContext.getContentResolver(); + Settings.Secure.putStringForUser(cr, Settings.Secure.ALWAYS_ON_VPN_APP, + getAlwaysOnPackage(), mUserHandle); + Settings.Secure.putIntForUser(cr, Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, + (mLockdown ? 1 : 0), mUserHandle); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + /** + * Set and save always-on package and lockdown config + * @see Vpn#setAlwaysOnPackage(String, boolean) + * @see Vpn#saveAlwaysOnPackage() + * + * @return result of Vpn#setAndSaveAlwaysOnPackage(String, boolean) + */ + private synchronized boolean setAndSaveAlwaysOnPackage(String packageName, boolean lockdown) { + if (setAlwaysOnPackage(packageName, lockdown)) { + saveAlwaysOnPackage(); + return true; + } else { + return false; + } + } + + /** + * @return {@code true} if the service was started, the service was already connected, or there + * was no always-on VPN to start. {@code false} otherwise. + */ + public boolean startAlwaysOnVpn() { + final String alwaysOnPackage; + synchronized (this) { + alwaysOnPackage = getAlwaysOnPackage(); + // Skip if there is no service to start. + if (alwaysOnPackage == null) { + return true; + } + // Skip if the service is already established. This isn't bulletproof: it's not bound + // until after establish(), so if it's mid-setup onStartCommand will be sent twice, + // which may restart the connection. + if (getNetworkInfo().isConnected()) { + return true; + } + } + + // Start the VPN service declared in the app's manifest. + Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE); + serviceIntent.setPackage(alwaysOnPackage); + try { + return mContext.startServiceAsUser(serviceIntent, UserHandle.of(mUserHandle)) != null; + } catch (RuntimeException e) { + Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e); + return false; + } + } + + /** * Prepare for a VPN application. This method is designed to solve * race conditions. It first compares the current prepared package * with {@code oldPackage}. If they are the same, the prepared @@ -270,11 +403,12 @@ public class Vpn { * * - oldPackage non-null, newPackage null: App calling VpnService#prepare(). * - oldPackage null, newPackage non-null: ConfirmDialog calling prepareVpn(). - * - oldPackage non-null, newPackage=LEGACY_VPN: Used internally to disconnect + * - oldPackage null, newPackage=LEGACY_VPN: Used internally to disconnect * and revoke any current app VPN and re-prepare legacy vpn. * - * TODO: Rename the variables - or split this method into two - and end this - * confusion. + * TODO: Rename the variables - or split this method into two - and end this confusion. + * TODO: b/29032008 Migrate code from prepare(oldPackage=non-null, newPackage=LEGACY_VPN) + * to prepare(oldPackage=null, newPackage=LEGACY_VPN) * * @param oldPackage The package name of the old VPN application * @param newPackage The package name of the new VPN application @@ -284,10 +418,7 @@ public class Vpn { public synchronized boolean prepare(String oldPackage, String newPackage) { if (oldPackage != null) { // Stop an existing always-on VPN from being dethroned by other apps. - // TODO: Replace TextUtils.equals by isCurrentPreparedPackage when ConnectivityService - // can unset always-on after always-on package is uninstalled. Make sure when package - // is reinstalled, the consent dialog is not shown. - if (mAlwaysOn && !TextUtils.equals(mPackage, oldPackage)) { + if (mAlwaysOn && !isCurrentPreparedPackage(oldPackage)) { return false; } @@ -318,9 +449,7 @@ public class Vpn { enforceControlPermission(); // Stop an existing always-on VPN from being dethroned by other apps. - // TODO: Replace TextUtils.equals by isCurrentPreparedPackage when ConnectivityService - // can unset always-on after always-on package is uninstalled - if (mAlwaysOn && !TextUtils.equals(mPackage, newPackage)) { + if (mAlwaysOn && !isCurrentPreparedPackage(newPackage)) { return false; } @@ -862,6 +991,7 @@ public class Vpn { setVpnForcedLocked(false); mAlwaysOn = false; + unregisterPackageChangeReceiverLocked(); // Quit any active connections agentDisconnect(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 05f5b8f1ac6c..07dc404e08db 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1448,6 +1448,9 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" -s: short summary"); pw.println(" -d: only list dangerous permissions"); pw.println(" -u: list only the permissions users will see"); + pw.println(" dump-profiles TARGET-PACKAGE"); + pw.println(" Dumps method/class profile files to"); + pw.println(" /data/misc/profman/TARGET-PACKAGE.txt"); pw.println(" resolve-activity [--brief] [--components] [--user USER_ID] INTENT"); pw.println(" Prints the activity that resolves to the given Intent."); pw.println(" query-activities [--brief] [--components] [--user USER_ID] INTENT"); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 66bb24d02de4..698774441cca 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -2589,15 +2589,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { final PhoneWindow win = new PhoneWindow(context); win.setIsStartingWindow(true); - final WindowManager.LayoutParams params = win.getAttributes(); final Resources r = context.getResources(); - CharSequence label = r.getText(labelRes); - // Only change the accessibility title if the label is localized - if (label != null) { - win.setTitle(label, true); - } else { - win.setTitle(nonLocalizedLabel, false); - } + win.setTitle(r.getText(labelRes, nonLocalizedLabel)); win.setType( WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); @@ -2631,6 +2624,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); + final WindowManager.LayoutParams params = win.getAttributes(); params.token = appToken; params.packageName = packageName; params.windowAnimations = win.getWindowStyle().getResourceId( diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 8be5dfb3c7fd..101f56f49241 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -1203,6 +1203,9 @@ final class AccessibilityController { window.layer = windowState.mLayer; window.token = windowState.mClient.asBinder(); window.title = windowState.mAttrs.accessibilityTitle; + if (window.title == null) { + window.title = windowState.mAttrs.getTitle(); + } window.accessibilityIdOfAnchor = windowState.mAttrs.accessibilityIdOfAnchor; WindowState attachedWindow = windowState.mAttachedWindow; |