diff options
Diffstat (limited to 'core')
63 files changed, 899 insertions, 354 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index e8ab109..9c2e208 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6473,20 +6473,22 @@ public class Activity extends ContextThemeWrapper } private void dispatchRequestPermissionsResult(int requestCode, Intent data) { - String[] permissions = data.getStringArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES); - final int[] grantResults = data.getIntArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS); + // If the package installer crashed we may have not data - best effort. + String[] permissions = (data != null) ? data.getStringArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0]; + final int[] grantResults = (data != null) ? data.getIntArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS) : new int[0]; onRequestPermissionsResult(requestCode, permissions, grantResults); } private void dispatchRequestPermissionsResultToFragment(int requestCode, Intent data, - Fragment fragement) { - String[] permissions = data.getStringArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES); - final int[] grantResults = data.getIntArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS); - fragement.onRequestPermissionsResult(requestCode, permissions, grantResults); + Fragment fragment) { + // If the package installer crashed we may have not data - best effort. + String[] permissions = (data != null) ? data.getStringArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0]; + final int[] grantResults = (data != null) ? data.getIntArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS) : new int[0]; + fragment.onRequestPermissionsResult(requestCode, permissions, grantResults); } class HostCallbacks extends FragmentHostCallback<Activity> { diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 8a61ec6..9faadd3 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -229,8 +229,12 @@ public class AppOpsManager { public static final int OP_READ_CELL_BROADCASTS = 57; /** @hide Inject mock location into the system. */ public static final int OP_MOCK_LOCATION = 58; + /** @hide Read external storage. */ + public static final int OP_READ_EXTERNAL_STORAGE = 59; + /** @hide Write external storage. */ + public static final int OP_WRITE_EXTERNAL_STORAGE = 60; /** @hide */ - public static final int _NUM_OP = 59; + public static final int _NUM_OP = 61; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -313,6 +317,12 @@ public class AppOpsManager { /** Inject mock location into the system. */ public static final String OPSTR_MOCK_LOCATION = "android:mock_location"; + /** Read external storage. */ + public static final String OPSTR_READ_EXTERNAL_STORAGE + = "android:read_external_storage"; + /** Write external storage. */ + public static final String OPSTR_WRITE_EXTERNAL_STORAGE + = "android:write_external_storage"; /** * This maps each operation to the operation that serves as the @@ -381,7 +391,9 @@ public class AppOpsManager { OP_USE_FINGERPRINT, OP_BODY_SENSORS, OP_READ_CELL_BROADCASTS, - OP_MOCK_LOCATION + OP_MOCK_LOCATION, + OP_READ_EXTERNAL_STORAGE, + OP_WRITE_EXTERNAL_STORAGE }; /** @@ -447,7 +459,9 @@ public class AppOpsManager { OPSTR_USE_FINGERPRINT, OPSTR_BODY_SENSORS, OPSTR_READ_CELL_BROADCASTS, - OPSTR_MOCK_LOCATION + OPSTR_MOCK_LOCATION, + OPSTR_READ_EXTERNAL_STORAGE, + OPSTR_WRITE_EXTERNAL_STORAGE }; /** @@ -513,7 +527,9 @@ public class AppOpsManager { "USE_FINGERPRINT", "BODY_SENSORS", "READ_CELL_BROADCASTS", - "MOCK_LOCATION" + "MOCK_LOCATION", + "OPSTR_READ_EXTERNAL_STORAGE", + "OPSTR_WRITE_EXTERNAL_STORAGE", }; /** @@ -579,7 +595,9 @@ public class AppOpsManager { Manifest.permission.USE_FINGERPRINT, Manifest.permission.BODY_SENSORS, Manifest.permission.READ_CELL_BROADCASTS, - null + null, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, }; /** @@ -646,7 +664,9 @@ public class AppOpsManager { null, // USE_FINGERPRINT null, // BODY_SENSORS null, // READ_CELL_BROADCASTS - null // MOCK_LOCATION + null, // MOCK_LOCATION + null, // READ_EXTERNAL_STORAGE + null // WRITE_EXTERNAL_STORAGE }; /** @@ -712,7 +732,9 @@ public class AppOpsManager { false, // USE_FINGERPRINT false, // BODY_SENSORS false, // READ_CELL_BROADCASTS - false // MOCK_LOCATION + false, // MOCK_LOCATION + false, // READ_EXTERNAL_STORAGE + false // WRITE_EXTERNAL_STORAGE }; /** @@ -777,7 +799,9 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, - AppOpsManager.MODE_ERRORED // OP_MOCK_LOCATION + AppOpsManager.MODE_ERRORED, // OP_MOCK_LOCATION + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED }; /** @@ -846,6 +870,8 @@ public class AppOpsManager { false, false, false, + false, + false, false }; diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index 903411e..13030ca 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -717,6 +717,7 @@ final class BackStackRecord extends FragmentTransaction implements break; case OP_REPLACE: { Fragment f = op.fragment; + int containerId = f.mContainerId; if (mManager.mAdded != null) { for (int i = 0; i < mManager.mAdded.size(); i++) { Fragment old = mManager.mAdded.get(i); @@ -724,7 +725,7 @@ final class BackStackRecord extends FragmentTransaction implements Log.v(TAG, "OP_REPLACE: adding=" + f + " old=" + old); } - if (f == null || old.mContainerId == f.mContainerId) { + if (old.mContainerId == containerId) { if (old == f) { op.fragment = f = null; } else { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d53157b..d28ff51 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3612,7 +3612,10 @@ public class DevicePolicyManager { * @see UserHandle * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the * user could not be created. + * + * @deprecated From {@link android.os.Build.VERSION_CODES#MNC} */ + @Deprecated public UserHandle createUser(@NonNull ComponentName admin, String name) { try { return mService.createUser(admin, name); @@ -3646,7 +3649,10 @@ public class DevicePolicyManager { * @see UserHandle * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the * user could not be created. + * + * @deprecated From {@link android.os.Build.VERSION_CODES#MNC} */ + @Deprecated public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name, String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) { try { @@ -3962,24 +3968,27 @@ public class DevicePolicyManager { * <li>{@link Settings.Global#ADB_ENABLED}</li> * <li>{@link Settings.Global#AUTO_TIME}</li> * <li>{@link Settings.Global#AUTO_TIME_ZONE}</li> - * <li>{@link Settings.Global#BLUETOOTH_ON} - * Changing this setting has not effect as of {@link android.os.Build.VERSION_CODES#MNC}. Use - * {@link android.bluetooth.BluetoothAdapter#enable()} and - * {@link android.bluetooth.BluetoothAdapter#disable()} instead.</li> * <li>{@link Settings.Global#DATA_ROAMING}</li> - * <li>{@link Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}</li> - * <li>{@link Settings.Global#MODE_RINGER}</li> - * <li>{@link Settings.Global#NETWORK_PREFERENCE}</li> * <li>{@link Settings.Global#USB_MASS_STORAGE_ENABLED}</li> - * <li>{@link Settings.Global#WIFI_ON} - * Changing this setting has not effect as of {@link android.os.Build.VERSION_CODES#MNC}. Use - * {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} instead.</li> * <li>{@link Settings.Global#WIFI_SLEEP_POLICY}</li> * <li>{@link Settings.Global#STAY_ON_WHILE_PLUGGED_IN} - * This setting is only available from {@link android.os.Build.VERSION_CODES#MNC} onwards - * and can only be set if {@link #setMaximumTimeToLock} is not used to set a timeout.</li> + * This setting is only available from {@link android.os.Build.VERSION_CODES#MNC} onwards + * and can only be set if {@link #setMaximumTimeToLock} is not used to set a timeout.</li> * <li>{@link Settings.Global#WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN}</li> * </ul> + * <p>Changing the following settings has no effect as of + * {@link android.os.Build.VERSION_CODES#MNC}: + * <ul> + * <li>{@link Settings.Global#BLUETOOTH_ON}. + * Use {@link android.bluetooth.BluetoothAdapter#enable()} and + * {@link android.bluetooth.BluetoothAdapter#disable()} instead.</li> + * <li>{@link Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}</li> + * <li>{@link Settings.Global#MODE_RINGER}. + * Use {@link android.media.AudioManager#setRingerMode(int)} instead.</li> + * <li>{@link Settings.Global#NETWORK_PREFERENCE}</li> + * <li>{@link Settings.Global#WIFI_ON}. + * Use {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} instead.</li> + * </ul> * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param setting The name of the setting to update. diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java index 07b2d57..cddf47a 100644 --- a/core/java/android/app/assist/AssistContent.java +++ b/core/java/android/app/assist/AssistContent.java @@ -12,7 +12,6 @@ import android.os.Parcelable; * assistant at the user's request. This is filled in by * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. */ -@Deprecated public class AssistContent implements Parcelable { private boolean mIsAppProvidedIntent = false; private Intent mIntent; diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index 369b692..24647f3 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -372,13 +372,4 @@ public final class UsageEvents implements Parcelable { return new UsageEvents[size]; } }; - - @Override - protected void finalize() throws Throwable { - super.finalize(); - if (mParcel != null) { - mParcel.recycle(); - mParcel = null; - } - } } diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index d37dda0..6ede29b 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -1593,7 +1593,11 @@ public abstract class ContentResolver { @NonNull ContentObserver observer) { Preconditions.checkNotNull(uri, "uri"); Preconditions.checkNotNull(observer, "observer"); - registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId()); + registerContentObserver( + ContentProvider.getUriWithoutUserId(uri), + notifyForDescendents, + observer, + ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId())); } /** @hide - designated user version */ @@ -1659,7 +1663,11 @@ public abstract class ContentResolver { public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer, boolean syncToNetwork) { Preconditions.checkNotNull(uri, "uri"); - notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId()); + notifyChange( + ContentProvider.getUriWithoutUserId(uri), + observer, + syncToNetwork, + ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId())); } /** diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index cea6e99..2b83d86 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -31,7 +31,6 @@ import android.content.pm.IPackageDeleteObserver2; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; -import android.content.pm.IPackagesProvider; import android.content.pm.IOnPermissionsChangeListener; import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.InstrumentationInfo; @@ -504,7 +503,7 @@ interface IPackageManager { void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener); void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener); - void grantDefaultPermissions(int userId); - void setCarrierAppPackagesProvider(in IPackagesProvider provider); int getMountExternalMode(int uid); + + void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId); } diff --git a/core/java/android/content/pm/IPackagesProvider.aidl b/core/java/android/content/pm/IPackagesProvider.aidl deleted file mode 100644 index 7d76c88..0000000 --- a/core/java/android/content/pm/IPackagesProvider.aidl +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.pm; - -/** {@hide} */ -interface IPackagesProvider { - String[] getPackages(int userId); -} diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 7599bd6..dbaba49 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -55,4 +55,30 @@ public abstract class PackageManagerInternal { * @param provider The packages provider. */ public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider); + + /** + * Sets the SMS packages provider. + * @param provider The packages provider. + */ + public abstract void setSmsAppPackagesProvider(PackagesProvider provider); + + /** + * Sets the dialer packages provider. + * @param provider The packages provider. + */ + public abstract void setDialerAppPackagesProvider(PackagesProvider provider); + + /** + * Requests granting of the default permissions to the current default SMS app. + * @param packageName The default SMS package name. + * @param userId The user for which to grant the permissions. + */ + public abstract void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId); + + /** + * Requests granting of the default permissions to the current default dialer app. + * @param packageName The default dialer package name. + * @param userId The user for which to grant the permissions. + */ + public abstract void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index faf71ee..64376c1 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1505,7 +1505,8 @@ public class PackageParser { if (!parseUsesPermission(pkg, res, parser, attrs)) { return null; } - } else if (tagName.equals("uses-permission-sdk-m")) { + } else if (tagName.equals("uses-permission-sdk-m") + || tagName.equals("uses-permission-sdk-23")) { if (!parseUsesPermission(pkg, res, parser, attrs)) { return null; } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 80476ea..12cd5f1 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2565,7 +2565,7 @@ public class ConnectivityManager { * replaced by this one, effectively releasing the previous {@link NetworkRequest}. * <p> * The request may be released normally by calling - * {@link #releaseNetworkRequest(android.app.PendingIntent)}. + * {@link #unregisterNetworkCallback(android.app.PendingIntent)}. * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * @param request {@link NetworkRequest} describing this request. @@ -2619,6 +2619,19 @@ public class ConnectivityManager { } /** + * Unregisters a callback previously registered via + * {@link #registerNetworkCallback(NetworkRequest, android.app.PendingIntent)}. + * + * @param operation A PendingIntent equal (as defined by {@link Intent#filterEquals}) to the + * PendingIntent passed to + * {@link #registerNetworkCallback(NetworkRequest, android.app.PendingIntent)}. + * Cannot be null. + */ + public void unregisterNetworkCallback(PendingIntent operation) { + releaseNetworkRequest(operation); + } + + /** * Informs the system whether it should switch to {@code network} regardless of whether it is * validated or not. If {@code accept} is true, and the network was explicitly selected by the * user (e.g., by selecting a Wi-Fi network in the Settings app), then the network will become diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 31aedad..cfd5bf1 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -517,7 +517,7 @@ public final class LinkProperties implements Parcelable { * Note that Http Proxies are only a hint - the system recommends their use, but it does * not enforce it and applications may ignore them. * - * @param proxy A {@link ProxyInfo} defining the Http Proxy to use on this link. + * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link. * @hide */ public void setHttpProxy(ProxyInfo proxy) { @@ -774,6 +774,43 @@ public final class LinkProperties implements Parcelable { } /** + * Evaluate whether the {@link InetAddress} is considered reachable. + * + * @return {@code true} if the given {@link InetAddress} is considered reachable, + * {@code false} otherwise. + * @hide + */ + public boolean isReachable(InetAddress ip) { + final List<RouteInfo> allRoutes = getAllRoutes(); + // If we don't have a route to this IP address, it's not reachable. + final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip); + if (bestRoute == null) { + return false; + } + + // TODO: better source address evaluation for destination addresses. + + if (ip instanceof Inet4Address) { + // For IPv4, it suffices for now to simply have any address. + return hasIPv4Address(); + } else if (ip instanceof Inet6Address) { + if (ip.isLinkLocalAddress()) { + // For now, just make sure link-local destinations have + // scopedIds set, since transmits will generally fail otherwise. + // TODO: verify it matches the ifindex of one of the interfaces. + return (((Inet6Address)ip).getScopeId() != 0); + } else { + // For non-link-local destinations check that either the best route + // is directly connected or that some global preferred address exists. + // TODO: reconsider all cases (disconnected ULA networks, ...). + return (!bestRoute.hasGateway() || hasGlobalIPv6Address()); + } + } + + return false; + } + + /** * Compares this {@code LinkProperties} interface name against the target * * @param target LinkProperties to compare. diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index 64c2bc2..23d05bd 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -40,7 +40,7 @@ import java.util.List; * NFC card emulation services. * * For a general introduction into NFC card emulation, - * please read the <a href="{@docRoot}guide/topics/nfc/ce.html"> + * please read the <a href="{@docRoot}guide/topics/connectivity/nfc/hce.html"> * NFC card emulation developer guide</a>.</p> * * <p class="note">Use of this class requires the diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 7fda30a..fe323f3 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -184,6 +184,7 @@ public abstract class BatteryStats implements Parcelable { private static final String UID_DATA = "uid"; private static final String APK_DATA = "apk"; private static final String PROCESS_DATA = "pr"; + private static final String CPU_DATA = "cpu"; private static final String SENSOR_DATA = "sr"; private static final String VIBRATOR_DATA = "vib"; private static final String FOREGROUND_DATA = "fg"; @@ -457,8 +458,13 @@ public abstract class BatteryStats implements Parcelable { public abstract long getSystemCpuTimeUs(int which); /** + * Get the total cpu power consumed (in milli-ampere-microseconds). + */ + public abstract long getCpuPowerMaUs(int which); + + /** * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed. - * @param speedStep the index of the CPU speed. This is not the actual speed of the CPU. + * @param step the index of the CPU speed. This is not the actual speed of the CPU. * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. * @see BatteryStats#getCpuSpeedSteps() */ @@ -2905,6 +2911,14 @@ public abstract class BatteryStats implements Parcelable { dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes); } + final long userCpuTimeUs = u.getUserCpuTimeUs(which); + final long systemCpuTimeUs = u.getSystemCpuTimeUs(which); + final long powerCpuMaUs = u.getCpuPowerMaUs(which); + if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) { + dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000, + powerCpuMaUs / 1000); + } + final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); for (int ipr=processStats.size()-1; ipr>=0; ipr--) { @@ -2970,6 +2984,10 @@ public abstract class BatteryStats implements Parcelable { printer.print(BatteryStatsHelper.makemAh(power)); } + private void printmAh(StringBuilder sb, double power) { + sb.append(BatteryStatsHelper.makemAh(power)); + } + /** * Temporary for settings. */ @@ -4028,13 +4046,17 @@ public abstract class BatteryStats implements Parcelable { final long userCpuTimeUs = u.getUserCpuTimeUs(which); final long systemCpuTimeUs = u.getSystemCpuTimeUs(which); - if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) { + final long powerCpuMaUs = u.getCpuPowerMaUs(which); + if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) { sb.setLength(0); sb.append(prefix); sb.append(" Total cpu time: u="); formatTimeMs(sb, userCpuTimeUs / 1000); sb.append("s="); formatTimeMs(sb, systemCpuTimeUs / 1000); + sb.append("p="); + printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0)); + sb.append("mAh"); pw.println(sb.toString()); } diff --git a/core/java/android/os/DeadObjectException.java b/core/java/android/os/DeadObjectException.java index 94c5387..e06b0f9 100644 --- a/core/java/android/os/DeadObjectException.java +++ b/core/java/android/os/DeadObjectException.java @@ -25,4 +25,8 @@ public class DeadObjectException extends RemoteException { public DeadObjectException() { super(); } + + public DeadObjectException(String message) { + super(message); + } } diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index 6874e77..511bd5f 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -179,6 +179,19 @@ public final class UserHandle implements Parcelable { } /** + * Returns the app id for a given shared app gid. + * @hide + */ + public static final int getAppIdFromSharedAppGid(int gid) { + final int noUserGid = getAppId(gid); + if (noUserGid < Process.FIRST_SHARED_APPLICATION_GID || + noUserGid > Process.LAST_SHARED_APPLICATION_GID) { + throw new IllegalArgumentException(Integer.toString(gid) + " is not a shared app gid"); + } + return (noUserGid + Process.FIRST_APPLICATION_UID) - Process.FIRST_SHARED_APPLICATION_GID; + } + + /** * Generate a text representation of the uid, breaking out its individual * components -- user, app, isolated, etc. * @hide diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 6384af3..b104135 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -572,6 +572,16 @@ public class UserManager { } /** + * @hide + * Returns whether the caller is running as an admin user. There can be more than one admin + * user. + */ + public boolean isAdminUser() { + UserInfo user = getUserInfo(UserHandle.myUserId()); + return user != null ? user.isAdmin() : false; + } + + /** * Used to check if the user making this call is linked to another user. Linked users may have * a reduced number of available apps, app restrictions and account restrictions. * @return whether the user making this call is a linked user diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 9b5fbfa..e5afdde 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -562,6 +562,21 @@ public final class Settings { "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS"; /** + * Activity Action: Show settings to toggle permission to draw on top of + * other apps. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MANAGE_OVERLAY_PERMISSION = + "android.settings.MANAGE_OVERLAY_PERMISSION"; + + /** * Activity Action: Show screen of details about a particular application. * <p> * In some cases, a matching Activity may not exist, so ensure you @@ -5444,6 +5459,14 @@ public final class Settings { public static final String ASSIST_STRUCTURE_ENABLED = "assist_structure_enabled"; /** + * Specifies whether a screenshot of the screen contents will be sent to the assist + * application (active voice interaction service). + * + * @hide + */ + public static final String ASSIST_SCREENSHOT_ENABLED = "assist_screenshot_enabled"; + + /** * Names of the service components that the current user has explicitly allowed to * see all of the user's notifications, separated by ':'. * diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index 8119049..549c93e 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -172,15 +172,6 @@ public class VoiceInteractionService extends Service { } } - /** @hide */ - public void startSession(Bundle args, int flags) { - showSession(args, flags); - } - /** @hide */ - public void startSession(Bundle args) { - startSession(args, 0); - } - @Override public void onCreate() { super.onCreate(); diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index f9e216a..7eb936a 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -71,7 +71,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; */ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCallbacks2 { static final String TAG = "VoiceInteractionSession"; - static final boolean DEBUG = true; + static final boolean DEBUG = false; /** * Flag received in {@link #onShow}: originator requested that the session be started with @@ -175,6 +175,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall CommandRequest request = new CommandRequest(callingPackage, Binder.getCallingUid(), callback, VoiceInteractionSession.this, command, extras); + addRequest(request); mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(MSG_START_COMMAND, request)); return request.mInterface; @@ -249,16 +250,12 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } }; - /** @hide */ - public static class Caller { - } - /** * Base class representing a request from a voice-driver app to perform a particular * voice operation with the user. See related subclasses for the types of requests * that are possible. */ - public static class Request extends Caller { + public static class Request { final IVoiceInteractorRequest mInterface = new IVoiceInteractorRequest.Stub() { @Override public void cancel() throws RemoteException { @@ -319,74 +316,8 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } } - /** @hide */ - public void sendConfirmResult(boolean confirmed, Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface - + " confirmed=" + confirmed + " result=" + result); - finishRequest(); - mCallback.deliverConfirmationResult(mInterface, confirmed, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendPickOptionResult(boolean finished, - VoiceInteractor.PickOptionRequest.Option[] selections, Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendPickOptionResult: req=" + mInterface - + " finished=" + finished + " selections=" + selections - + " result=" + result); - if (finished) { - finishRequest(); - } - mCallback.deliverPickOptionResult(mInterface, finished, selections, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendCompleteVoiceResult(Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendCompleteVoiceResult: req=" + mInterface - + " result=" + result); - finishRequest(); - mCallback.deliverCompleteVoiceResult(mInterface, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendAbortVoiceResult(Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface - + " result=" + result); - finishRequest(); - mCallback.deliverAbortVoiceResult(mInterface, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendCommandResult(boolean finished, Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface - + " result=" + result); - if (finished) { - finishRequest(); - } - mCallback.deliverCommandResult(mInterface, finished, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendCancelResult() { - cancel(); - } - /** - * ASk the app to cancelLocked this current request. + * Ask the app to cancel this current request. */ public void cancel() { try { @@ -440,7 +371,13 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * VoiceInteractor.ConfirmationRequest.onConfirmationResult}. */ public void sendConfirmationResult(boolean confirmed, Bundle result) { - sendConfirmResult(confirmed, result); + try { + if (DEBUG) Log.d(TAG, "sendConfirmationResult: req=" + mInterface + + " confirmed=" + confirmed + " result=" + result); + finishRequest(); + mCallback.deliverConfirmationResult(mInterface, confirmed, result); + } catch (RemoteException e) { + } } } @@ -487,6 +424,20 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall return mOptions; } + void sendPickOptionResult(boolean finished, + VoiceInteractor.PickOptionRequest.Option[] selections, Bundle result) { + try { + if (DEBUG) Log.d(TAG, "sendPickOptionResult: req=" + mInterface + + " finished=" + finished + " selections=" + selections + + " result=" + result); + if (finished) { + finishRequest(); + } + mCallback.deliverPickOptionResult(mInterface, finished, selections, result); + } catch (RemoteException e) { + } + } + /** * Report an intermediate option selection from the request, without completing it (the * request is still active and the app is waiting for the final option selection), @@ -553,7 +504,13 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * VoiceInteractor.CompleteVoiceRequest.onCompleteResult}. */ public void sendCompleteResult(Bundle result) { - sendCompleteVoiceResult(result); + try { + if (DEBUG) Log.d(TAG, "sendCompleteVoiceResult: req=" + mInterface + + " result=" + result); + finishRequest(); + mCallback.deliverCompleteVoiceResult(mInterface, result); + } catch (RemoteException e) { + } } } @@ -596,7 +553,13 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * VoiceInteractor.AbortVoiceRequest.onAbortResult}. */ public void sendAbortResult(Bundle result) { - sendAbortVoiceResult(result); + try { + if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface + + " result=" + result); + finishRequest(); + mCallback.deliverAbortVoiceResult(mInterface, result); + } catch (RemoteException e) { + } } } @@ -621,6 +584,18 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall return mCommand; } + void sendCommandResult(boolean finished, Bundle result) { + try { + if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface + + " result=" + result); + if (finished) { + finishRequest(); + } + mCallback.deliverCommandResult(mInterface, finished, result); + } catch (RemoteException e) { + } + } + /** * Report an intermediate result of the request, without completing it (the request * is still active and the app is waiting for the final result), resulting in a call to @@ -829,11 +804,10 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } } - void doCreate(IVoiceInteractionManagerService service, IBinder token, Bundle args, - int startFlags) { + void doCreate(IVoiceInteractionManagerService service, IBinder token) { mSystemService = service; mToken = token; - onCreate(args, startFlags); + onCreate(); } void doShow(Bundle args, int flags, final IVoiceInteractionSessionShowCallback showCallback) { @@ -919,11 +893,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall mContentFrame = (FrameLayout)mRootView.findViewById(android.R.id.content); } - /** @hide */ - public void show() { - show(null, 0); - } - /** * Show the UI for this session. This asks the system to go through the process of showing * your UI, which will eventually culminate in {@link #onShow}. This is similar to calling @@ -958,14 +927,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } } - /** @hide */ - public void showWindow() { - } - - /** @hide */ - public void hideWindow() { - } - /** * You can call this to customize the theme used by your IME's window. * This must be set before {@link #onCreate}, so you @@ -1062,7 +1023,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall if (mToken == null) { throw new IllegalStateException("Can't call before onCreate()"); } - hideWindow(); try { mSystemService.finish(mToken); } catch (RemoteException e) { @@ -1077,16 +1037,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall doOnCreate(); } - /** @hide */ - public void onCreate(Bundle args) { - doOnCreate(); - } - - /** @hide */ - public void onCreate(Bundle args, int showFlags) { - doOnCreate(); - } - private void doOnCreate() { mTheme = mTheme != 0 ? mTheme : com.android.internal.R.style.Theme_DeviceDefault_VoiceInteractionSession; @@ -1244,34 +1194,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall hide(); } - /** @hide */ - public boolean[] onGetSupportedCommands(Caller caller, String[] commands) { - return new boolean[commands.length]; - } - /** @hide */ - public void onConfirm(Caller caller, Request request, CharSequence prompt, - Bundle extras) { - } - /** @hide */ - public void onPickOption(Caller caller, Request request, CharSequence prompt, - VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras) { - } - /** @hide */ - public void onCompleteVoice(Caller caller, Request request, CharSequence message, - Bundle extras) { - request.sendCompleteVoiceResult(null); - } - /** @hide */ - public void onAbortVoice(Caller caller, Request request, CharSequence message, Bundle extras) { - request.sendAbortVoiceResult(null); - } - /** @hide */ - public void onCommand(Caller caller, Request request, String command, Bundle extras) { - } - /** @hide */ - public void onCancel(Request request) { - } - /** * Request to query for what extended commands the session supports. * @@ -1282,7 +1204,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * an array of all false entries. */ public boolean[] onGetSupportedCommands(String[] commands) { - return onGetSupportedCommands(new Caller(), commands); + return new boolean[commands.length]; } /** @@ -1293,7 +1215,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestConfirmation(ConfirmationRequest request) { - onConfirm(request, request, request.getPrompt(), request.getExtras()); } /** @@ -1303,8 +1224,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestPickOption(PickOptionRequest request) { - onPickOption(request, request, request.getPrompt(), request.getOptions(), - request.getExtras()); } /** @@ -1317,7 +1236,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestCompleteVoice(CompleteVoiceRequest request) { - onCompleteVoice(request, request, request.getMessage(), request.getExtras()); } /** @@ -1330,7 +1248,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestAbortVoice(AbortVoiceRequest request) { - onAbortVoice(request, request, request.getMessage(), request.getExtras()); } /** @@ -1341,11 +1258,10 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestCommand(CommandRequest request) { - onCommand(request, request, request.getCommand(), request.getExtras()); } /** - * Called when the {@link android.app.VoiceInteractor} has asked to cancelLocked a {@link Request} + * Called when the {@link android.app.VoiceInteractor} has asked to cancel a {@link Request} * that was previously delivered to {@link #onRequestConfirmation}, * {@link #onRequestPickOption}, {@link #onRequestCompleteVoice}, {@link #onRequestAbortVoice}, * or {@link #onRequestCommand}. @@ -1353,6 +1269,5 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The request that is being canceled. */ public void onCancelRequest(Request request) { - onCancel(request); } } diff --git a/core/java/android/service/voice/VoiceInteractionSessionService.java b/core/java/android/service/voice/VoiceInteractionSessionService.java index 8f988f3..fb9f973 100644 --- a/core/java/android/service/voice/VoiceInteractionSessionService.java +++ b/core/java/android/service/voice/VoiceInteractionSessionService.java @@ -109,7 +109,7 @@ public abstract class VoiceInteractionSessionService extends Service { mSession = onNewSession(args); try { mSystemService.deliverNewSession(token, mSession.mSession, mSession.mInteractor); - mSession.doCreate(mSystemService, token, args, startFlags); + mSession.doCreate(mSystemService, token); } catch (RemoteException e) { } } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 8952807..bbdb0e1 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -649,7 +649,7 @@ public abstract class WallpaperService extends Service { com.android.internal.R.style.Animation_Wallpaper; mInputChannel = new InputChannel(); if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE, - Display.DEFAULT_DISPLAY, mContentInsets, mStableInsets, + Display.DEFAULT_DISPLAY, mContentInsets, mStableInsets, mOutsets, mInputChannel) < 0) { Log.w(TAG, "Failed to add window while updating wallpaper surface."); return; diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index 585fc4e..f9dd7eb 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -452,6 +452,7 @@ public abstract class Visibility extends Transition { DisappearListener disappearListener = new DisappearListener(viewToKeep, finalVisibility, isForcedVisibility); animator.addListener(disappearListener); + animator.addPauseListener(disappearListener); addListener(disappearListener); } else if (!isForcedVisibility) { viewToKeep.setTransitionVisibility(originalVisibility); diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java index c3aafde..752240f 100644 --- a/core/java/android/view/ActionProvider.java +++ b/core/java/android/view/ActionProvider.java @@ -237,6 +237,14 @@ public abstract class ActionProvider { } /** + * @hide + */ + public void reset() { + mVisibilityListener = null; + mSubUiVisibilityListener = null; + } + + /** * @hide Internal use only */ public interface SubUiVisibilityListener { diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 19253dd..73b4a6e 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -40,7 +40,7 @@ interface IWindowSession { out InputChannel outInputChannel); int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs, in int viewVisibility, in int layerStackId, out Rect outContentInsets, - out Rect outStableInsets, out InputChannel outInputChannel); + out Rect outStableInsets, out Rect outOutsets, out InputChannel outInputChannel); int addWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs, in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets); int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs, diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index e044f1e..f6119e2 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -434,7 +434,6 @@ public class ThreadedRenderer extends HardwareRenderer { private static class ProcessInitializer { static ProcessInitializer sInstance = new ProcessInitializer(); - static IGraphicsStats sGraphicsStatsService; private static IBinder sProcToken; private boolean mInitialized = false; @@ -449,19 +448,19 @@ public class ThreadedRenderer extends HardwareRenderer { } private static void initGraphicsStats(Context context, long renderProxy) { - IBinder binder = ServiceManager.getService("graphicsstats"); - if (binder == null) return; - - sGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder); - sProcToken = new Binder(); try { + IBinder binder = ServiceManager.getService("graphicsstats"); + if (binder == null) return; + IGraphicsStats graphicsStatsService = IGraphicsStats.Stub + .asInterface(binder); + sProcToken = new Binder(); final String pkg = context.getApplicationInfo().packageName; - ParcelFileDescriptor pfd = sGraphicsStatsService. + ParcelFileDescriptor pfd = graphicsStatsService. requestBufferForProcess(pkg, sProcToken); nSetProcessStatsBuffer(renderProxy, pfd.getFd()); pfd.close(); - } catch (Exception e) { - Log.w(LOG_TAG, "Could not acquire gfx stats buffer", e); + } catch (Throwable t) { + Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t); } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 23da6d2..63dd492 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -12288,6 +12288,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mRenderNode.offsetTopAndBottom(offset); if (isHardwareAccelerated()) { invalidateViewProperty(false, false); + invalidateParentIfNeededAndWasQuickRejected(); } else { if (!matrixIsIdentity) { invalidateViewProperty(false, true); @@ -12335,6 +12336,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mRenderNode.offsetLeftAndRight(offset); if (isHardwareAccelerated()) { invalidateViewProperty(false, false); + invalidateParentIfNeededAndWasQuickRejected(); } else { if (!matrixIsIdentity) { invalidateViewProperty(false, true); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index b53d93c..6dca26b 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3236,13 +3236,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager for (int i = 0; i < getChildCount(); i++) { View c = getChildAt(i); - Insets insets = c.getOpticalInsets(); - - drawRect(canvas, paint, - c.getLeft() + insets.left, - c.getTop() + insets.top, - c.getRight() - insets.right - 1, - c.getBottom() - insets.bottom - 1); + if (c.getVisibility() != View.GONE) { + Insets insets = c.getOpticalInsets(); + + drawRect(canvas, paint, + c.getLeft() + insets.left, + c.getTop() + insets.top, + c.getRight() - insets.right - 1, + c.getBottom() - insets.bottom - 1); + } } } @@ -3263,8 +3265,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager int lineWidth = dipsToPixels(1); for (int i = 0; i < getChildCount(); i++) { View c = getChildAt(i); - drawRectCorners(canvas, c.getLeft(), c.getTop(), c.getRight(), c.getBottom(), - paint, lineLength, lineWidth); + if (c.getVisibility() != View.GONE) { + drawRectCorners(canvas, c.getLeft(), c.getTop(), c.getRight(), c.getBottom(), + paint, lineLength, lineWidth); + } } } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 8b57d96..6d0d788 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -531,7 +531,8 @@ public final class ViewRootImpl implements ViewParent, collectViewAttributes(); res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), - mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel); + mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, + mAttachInfo.mOutsets, mInputChannel); } catch (RemoteException e) { mAdded = false; mView = null; @@ -1590,6 +1591,7 @@ public final class ViewRootImpl implements ViewParent, + " content=" + mPendingContentInsets.toShortString() + " visible=" + mPendingVisibleInsets.toShortString() + " visible=" + mPendingStableInsets.toShortString() + + " outsets=" + mPendingOutsets.toShortString() + " surface=" + mSurface); if (mPendingConfiguration.seq != 0) { diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index ca5f5ad..64210ea 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -879,13 +879,15 @@ public interface WindowManagerPolicy { * be correct. * * @param attrs The LayoutParams of the window. + * @param rotation Rotation of the display. * @param outContentInsets The areas covered by system windows, expressed as positive insets. * @param outStableInsets The areas covered by stable system windows irrespective of their * current visibility. Expressed as positive insets. + * @param outOutsets The areas that are not real display, but we would like to treat as such. * */ - public void getInsetHintLw(WindowManager.LayoutParams attrs, Rect outContentInsets, - Rect outStableInsets); + public void getInsetHintLw(WindowManager.LayoutParams attrs, int rotation, + Rect outContentInsets, Rect outStableInsets, Rect outOutsets); /** * Called when layout of the windows is finished. After this function has @@ -913,12 +915,13 @@ public interface WindowManagerPolicy { /** * Called following layout of all window to apply policy to each window. - * + * * @param win The window being positioned. - * @param attrs The LayoutParams of the window. + * @param attrs The LayoutParams of the window. + * @param attached For sub-windows, the window it is attached to. Otherwise null. */ public void applyPostLayoutPolicyLw(WindowState win, - WindowManager.LayoutParams attrs); + WindowManager.LayoutParams attrs, WindowState attached); /** * Called following layout of all windows and after policy has been applied diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index 87706ef..1464bb5 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -689,6 +689,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000; /** + * Represents the event of the assistant currently reading the users screen context. + */ + public static final int TYPE_ASSIST_READING_CONTEXT = 0x01000000; + + /** * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: * The type of change is not defined. */ @@ -1414,6 +1419,13 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par builder.append("TYPE_VIEW_CONTEXT_CLICKED"); eventTypeCount++; } + case TYPE_ASSIST_READING_CONTEXT: { + if (eventTypeCount > 0) { + builder.append(", "); + } + builder.append("TYPE_ASSIST_READING_CONTEXT"); + eventTypeCount++; + } break; } } diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index 770077d..602e1ab 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -245,6 +245,17 @@ public abstract class CompoundButton extends Button implements Checkable { } /** + * @hide + */ + @Override + public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { + super.onResolveDrawables(layoutDirection); + if (mButtonDrawable != null) { + mButtonDrawable.setLayoutDirection(layoutDirection); + } + } + + /** * @return the drawable used as the compound button image * @see #setButtonDrawable(Drawable) * @see #setButtonDrawable(int) diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index e0b2395..a1582f2 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -423,14 +423,14 @@ public class ImageView extends View { * * <p class="note">This does Bitmap reading and decoding on the UI * thread, which can cause a latency hiccup. If that's a concern, - * consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)} or + * consider using {@link #setImageDrawable(Drawable)} or * {@link #setImageBitmap(android.graphics.Bitmap)} and * {@link android.graphics.BitmapFactory} instead.</p> * - * @param uri The Uri of an image + * @param uri the Uri of an image, or {@code null} to clear the content */ @android.view.RemotableViewMethod - public void setImageURI(Uri uri) { + public void setImageURI(@Nullable Uri uri) { if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) { @@ -453,9 +453,10 @@ public class ImageView extends View { /** * Sets a drawable as the content of this ImageView. * - * @param drawable The drawable to set + * @param drawable the Drawable to set, or {@code null} to clear the + * content */ - public void setImageDrawable(Drawable drawable) { + public void setImageDrawable(@Nullable Drawable drawable) { if (mDrawable != drawable) { mResource = 0; mUri = null; @@ -475,16 +476,19 @@ public class ImageView extends View { /** * Sets the content of this ImageView to the specified Icon. * - * <p class="note">Depending on the Icon type, this may do Bitmap reading and decoding - * on the UI thread, which can cause UI jank. If that's a concern, consider using + * <p class="note">Depending on the Icon type, this may do Bitmap reading + * and decoding on the UI thread, which can cause UI jank. If that's a + * concern, consider using * {@link Icon#loadDrawableAsync(Context, Icon.OnDrawableLoadedListener, Handler)} - * and then {@link #setImageDrawable(android.graphics.drawable.Drawable)} instead.</p> + * and then {@link #setImageDrawable(android.graphics.drawable.Drawable)} + * instead.</p> * - * @param icon an Icon holding the desired image + * @param icon an Icon holding the desired image, or {@code null} to clear + * the content */ @android.view.RemotableViewMethod - public void setImageIcon(Icon icon) { - setImageDrawable(icon.loadDrawable(mContext)); + public void setImageIcon(@Nullable Icon icon) { + setImageDrawable(icon == null ? null : icon.loadDrawable(mContext)); } /** diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index 4dcc242..b5e08ca 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -659,7 +659,8 @@ public class LinearLayout extends ViewGroup { */ private boolean allViewsAreGoneBefore(int childIndex) { for (int i = childIndex - 1; i >= 0; i--) { - if (getVirtualChildAt(i).getVisibility() != GONE) { + View child = getVirtualChildAt(i); + if (child != null && child.getVisibility() != GONE) { return false; } } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 7b58b5b..422511f 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8837,12 +8837,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE); + info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); } if (isFocused()) { - if (canSelectText()) { - info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); - } if (canCopy()) { info.addAction(AccessibilityNodeInfo.ACTION_COPY); } @@ -8931,30 +8929,28 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } return false; case AccessibilityNodeInfo.ACTION_SET_SELECTION: { - if (isFocused() && canSelectText()) { - ensureIterableTextForAccessibilitySelectable(); - CharSequence text = getIterableTextForAccessibility(); - if (text == null) { - return false; + ensureIterableTextForAccessibilitySelectable(); + CharSequence text = getIterableTextForAccessibility(); + if (text == null) { + return false; + } + final int start = (arguments != null) ? arguments.getInt( + AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; + final int end = (arguments != null) ? arguments.getInt( + AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; + if ((getSelectionStart() != start || getSelectionEnd() != end)) { + // No arguments clears the selection. + if (start == end && end == -1) { + Selection.removeSelection((Spannable) text); + return true; } - final int start = (arguments != null) ? arguments.getInt( - AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; - final int end = (arguments != null) ? arguments.getInt( - AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; - if ((getSelectionStart() != start || getSelectionEnd() != end)) { - // No arguments clears the selection. - if (start == end && end == -1) { - Selection.removeSelection((Spannable) text); - return true; - } - if (start >= 0 && start <= end && end <= text.length()) { - Selection.setSelection((Spannable) text, start, end); - // Make sure selection mode is engaged. - if (mEditor != null) { - mEditor.startSelectionActionMode(); - } - return true; + if (start >= 0 && start <= end && end <= text.length()) { + Selection.setSelection((Spannable) text, start, end); + // Make sure selection mode is engaged. + if (mEditor != null) { + mEditor.startSelectionActionMode(); } + return true; } } } return false; diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java index ac17cbe..742173b 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java +++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java @@ -1302,4 +1302,131 @@ public class InputMethodUtils { return enabledInputMethodAndSubtypes; } } + + // For spell checker service manager. + // TODO: Should we have TextServicesUtils.java? + private static final Locale LOCALE_EN_US = new Locale("en", "US"); + private static final Locale LOCALE_EN_GB = new Locale("en", "GB"); + + /** + * Returns a list of {@link Locale} in the order of appropriateness for the default spell + * checker service. + * + * <p>If the system language is English, and the region is also explicitly specified in the + * system locale, the following fallback order will be applied.</p> + * <ul> + * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li> + * <li>(system-locale-language, system-locale-region)</li> + * <li>("en", "US")</li> + * <li>("en", "GB")</li> + * <li>("en")</li> + * </ul> + * + * <p>If the system language is English, but no region is specified in the system locale, + * the following fallback order will be applied.</p> + * <ul> + * <li>("en")</li> + * <li>("en", "US")</li> + * <li>("en", "GB")</li> + * </ul> + * + * <p>If the system language is not English, the following fallback order will be applied.</p> + * <ul> + * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li> + * <li>(system-locale-language, system-locale-region) (if exists)</li> + * <li>(system-locale-language) (if exists)</li> + * <li>("en", "US")</li> + * <li>("en", "GB")</li> + * <li>("en")</li> + * </ul> + * + * @param systemLocale the current system locale to be taken into consideration. + * @return a list of {@link Locale}. The first one is considered to be most appropriate. + */ + @VisibleForTesting + public static ArrayList<Locale> getSuitableLocalesForSpellChecker( + @Nullable final Locale systemLocale) { + final Locale systemLocaleLanguageCountryVariant; + final Locale systemLocaleLanguageCountry; + final Locale systemLocaleLanguage; + if (systemLocale != null) { + final String language = systemLocale.getLanguage(); + final boolean hasLanguage = !TextUtils.isEmpty(language); + final String country = systemLocale.getCountry(); + final boolean hasCountry = !TextUtils.isEmpty(country); + final String variant = systemLocale.getVariant(); + final boolean hasVariant = !TextUtils.isEmpty(variant); + if (hasLanguage && hasCountry && hasVariant) { + systemLocaleLanguageCountryVariant = new Locale(language, country, variant); + } else { + systemLocaleLanguageCountryVariant = null; + } + if (hasLanguage && hasCountry) { + systemLocaleLanguageCountry = new Locale(language, country); + } else { + systemLocaleLanguageCountry = null; + } + if (hasLanguage) { + systemLocaleLanguage = new Locale(language); + } else { + systemLocaleLanguage = null; + } + } else { + systemLocaleLanguageCountryVariant = null; + systemLocaleLanguageCountry = null; + systemLocaleLanguage = null; + } + + final ArrayList<Locale> locales = new ArrayList<>(); + if (systemLocaleLanguageCountryVariant != null) { + locales.add(systemLocaleLanguageCountryVariant); + } + + if (Locale.ENGLISH.equals(systemLocaleLanguage)) { + if (systemLocaleLanguageCountry != null) { + // If the system language is English, and the region is also explicitly specified, + // following fallback order will be applied. + // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null] + // - en_US [if systemLocaleLanguageCountry is non-null and not en_US] + // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB] + // - en + if (systemLocaleLanguageCountry != null) { + locales.add(systemLocaleLanguageCountry); + } + if (!LOCALE_EN_US.equals(systemLocaleLanguageCountry)) { + locales.add(LOCALE_EN_US); + } + if (!LOCALE_EN_GB.equals(systemLocaleLanguageCountry)) { + locales.add(LOCALE_EN_GB); + } + locales.add(Locale.ENGLISH); + } else { + // If the system language is English, but no region is specified, following + // fallback order will be applied. + // - en + // - en_US + // - en_GB + locales.add(Locale.ENGLISH); + locales.add(LOCALE_EN_US); + locales.add(LOCALE_EN_GB); + } + } else { + // If the system language is not English, the fallback order will be + // - systemLocaleLanguageCountry [if non-null] + // - systemLocaleLanguage [if non-null] + // - en_US + // - en_GB + // - en + if (systemLocaleLanguageCountry != null) { + locales.add(systemLocaleLanguageCountry); + } + if (systemLocaleLanguage != null) { + locales.add(systemLocaleLanguage); + } + locales.add(LOCALE_EN_US); + locales.add(LOCALE_EN_GB); + locales.add(Locale.ENGLISH); + } + return locales; + } } diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java index b78eca7..263e522 100644 --- a/core/java/com/android/internal/logging/MetricsLogger.java +++ b/core/java/com/android/internal/logging/MetricsLogger.java @@ -40,6 +40,10 @@ public class MetricsLogger implements MetricsConstants { public static final int ACTION_BRIGHTNESS = 218; public static final int ACTION_BRIGHTNESS_AUTO = 219; public static final int BRIGHTNESS_DIALOG = 220; + public static final int SYSTEM_ALERT_WINDOW_APPS = 221; + public static final int DREAMING = 222; + public static final int DOZING = 223; + // Temporary constants go here, to await migration to MetricsConstants. public static void visible(Context context, int category) throws IllegalArgumentException { diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index 6a85afb..264b8c1 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -480,6 +480,7 @@ public final class BatteryStatsHelper { final boolean forAllUsers = (asUsers.get(UserHandle.USER_ALL) != null); mStatsPeriod = mTypeBatteryRealtime; + BatterySipper osSipper = null; final SparseArray<? extends Uid> uidStats = mStats.getUidStats(); final int NU = uidStats.size(); for (int iu = 0; iu < NU; iu++) { @@ -526,15 +527,19 @@ public final class BatteryStatsHelper { } if (uid == 0) { - // The device has probably been awake for longer than the screen on - // time and application wake lock time would account for. Assign - // this remainder to the OS, if possible. - mWakelockPowerCalculator.calculateRemaining(app, mStats, mRawRealtime, - mRawUptime, mStatsType); - app.sumPower(); + osSipper = app; } } } + + if (osSipper != null) { + // The device has probably been awake for longer than the screen on + // time and application wake lock time would account for. Assign + // this remainder to the OS, if possible. + mWakelockPowerCalculator.calculateRemaining(osSipper, mStats, mRawRealtime, + mRawUptime, mStatsType); + osSipper.sumPower(); + } } private void addPhoneUsage() { diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 1bd821d..8b4b994 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -106,7 +106,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 129 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 130 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -4386,6 +4386,7 @@ public final class BatteryStatsImpl extends BatteryStats { LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase); LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase); + LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase); LongSamplingCounter[] mSpeedBins; /** @@ -4978,6 +4979,11 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override + public long getCpuPowerMaUs(int which) { + return mCpuPower.getCountLocked(which); + } + + @Override public long getTimeAtCpuSpeed(int step, int which) { if (step >= 0 && step < mSpeedBins.length) { if (mSpeedBins[step] != null) { @@ -5097,6 +5103,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime.reset(false); mSystemCpuTime.reset(false); + mCpuPower.reset(false); for (int i = 0; i < mSpeedBins.length; i++) { LongSamplingCounter c = mSpeedBins[i]; if (c != null) { @@ -5248,6 +5255,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime.detach(); mSystemCpuTime.detach(); + mCpuPower.detach(); for (int i = 0; i < mSpeedBins.length; i++) { LongSamplingCounter c = mSpeedBins[i]; if (c != null) { @@ -5427,6 +5435,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime.writeToParcel(out); mSystemCpuTime.writeToParcel(out); + mCpuPower.writeToParcel(out); out.writeInt(mSpeedBins.length); for (int i = 0; i < mSpeedBins.length; i++) { @@ -5618,6 +5627,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in); mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in); + mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in); int bins = in.readInt(); int steps = getCpuSpeedSteps(); @@ -7964,7 +7974,8 @@ public final class BatteryStatsImpl extends BatteryStats { mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null : new KernelUidCpuTimeReader.Callback() { @Override - public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) { + public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs, + long powerMaUs) { final Uid u = getUidStatsLocked(mapUid(uid)); // Accumulate the total system and user time. @@ -7978,7 +7989,7 @@ public final class BatteryStatsImpl extends BatteryStats { TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); - sb.append("\n"); + sb.append(" p=").append(powerMaUs / 1000).append("mAms\n"); } if (numWakelocksF > 0) { @@ -7994,11 +8005,13 @@ public final class BatteryStatsImpl extends BatteryStats { TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); + sb.append(" p=").append(powerMaUs / 1000).append("mAms"); Slog.d(TAG, sb.toString()); } u.mUserCpuTime.addCountLocked(userTimeUs); u.mSystemCpuTime.addCountLocked(systemTimeUs); + u.mCpuPower.addCountLocked(powerMaUs); // Add the cpu speeds to this UID. These are used as a ratio // for computing the power this UID used. @@ -9229,6 +9242,7 @@ public final class BatteryStatsImpl extends BatteryStats { u.mUserCpuTime.readSummaryFromParcelLocked(in); u.mSystemCpuTime.readSummaryFromParcelLocked(in); + u.mCpuPower.readSummaryFromParcelLocked(in); int NSB = in.readInt(); if (NSB > 100) { @@ -9575,6 +9589,7 @@ public final class BatteryStatsImpl extends BatteryStats { u.mUserCpuTime.writeSummaryFromParcelLocked(out); u.mSystemCpuTime.writeSummaryFromParcelLocked(out); + u.mCpuPower.writeSummaryFromParcelLocked(out); out.writeInt(u.mSpeedBins.length); for (int i = 0; i < u.mSpeedBins.length; i++) { diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index 41efd2c..e2d366a 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -30,7 +30,7 @@ import java.io.IOException; /** * Reads /proc/uid_cputime/show_uid_stat which has the line format: * - * uid: user_time_micro_seconds system_time_micro_seconds + * uid: user_time_micro_seconds system_time_micro_seconds power_in_milli-amp-micro_seconds * * This provides the time a UID's processes spent executing in user-space and kernel-space. * The file contains a monotonically increasing count of time for a single boot. This class @@ -46,11 +46,18 @@ public class KernelUidCpuTimeReader { * Callback interface for processing each line of the proc file. */ public interface Callback { - void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs); + /** + * @param uid UID of the app + * @param userTimeUs time spent executing in user space in microseconds + * @param systemTimeUs time spent executing in kernel space in microseconds + * @param powerMaUs power consumed executing, in milli-ampere microseconds + */ + void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs, long powerMaUs); } private SparseLongArray mLastUserTimeUs = new SparseLongArray(); private SparseLongArray mLastSystemTimeUs = new SparseLongArray(); + private SparseLongArray mLastPowerMaUs = new SparseLongArray(); private long mLastTimeReadUs = 0; /** @@ -70,50 +77,60 @@ public class KernelUidCpuTimeReader { final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10); final long userTimeUs = Long.parseLong(splitter.next(), 10); final long systemTimeUs = Long.parseLong(splitter.next(), 10); + final long powerMaUs = Long.parseLong(splitter.next(), 10) / 1000; if (callback != null) { long userTimeDeltaUs = userTimeUs; long systemTimeDeltaUs = systemTimeUs; + long powerDeltaMaUs = powerMaUs; int index = mLastUserTimeUs.indexOfKey(uid); if (index >= 0) { userTimeDeltaUs -= mLastUserTimeUs.valueAt(index); systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index); + powerDeltaMaUs -= mLastPowerMaUs.valueAt(index); final long timeDiffUs = nowUs - mLastTimeReadUs; - if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || + if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || powerDeltaMaUs < 0 || userTimeDeltaUs > timeDiffUs || systemTimeDeltaUs > timeDiffUs) { - StringBuilder sb = new StringBuilder("Malformed cpu data!\n"); + StringBuilder sb = new StringBuilder("Malformed cpu data for UID="); + sb.append(uid).append("!\n"); sb.append("Time between reads: "); TimeUtils.formatDuration(timeDiffUs / 1000, sb); - sb.append("ms\n"); + sb.append("\n"); sb.append("Previous times: u="); TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb); - sb.append("ms s="); + sb.append(" s="); TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb); - sb.append("ms\n"); + sb.append(" p=").append(mLastPowerMaUs.valueAt(index) / 1000); + sb.append("mAms\n"); + sb.append("Current times: u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); - sb.append("ms s="); + sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); - sb.append("ms\n"); - sb.append("Delta for UID=").append(uid).append(": u="); + sb.append(" p=").append(powerMaUs / 1000); + sb.append("mAms\n"); + sb.append("Delta: u="); TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb); - sb.append("ms s="); + sb.append(" s="); TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb); - sb.append("ms"); + sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms"); Slog.wtf(TAG, sb.toString()); userTimeDeltaUs = 0; systemTimeDeltaUs = 0; + powerDeltaMaUs = 0; } } - if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0) { - callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs); + if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0 || powerDeltaMaUs != 0) { + callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs, + powerDeltaMaUs); } } mLastUserTimeUs.put(uid, userTimeUs); mLastSystemTimeUs.put(uid, systemTimeUs); + mLastPowerMaUs.put(uid, powerMaUs); } } catch (IOException e) { Slog.e(TAG, "Failed to read uid_cputime", e); diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index aea1585..63bfbe5 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -44,7 +44,7 @@ interface IStatusBarService // You need the STATUS_BAR_SERVICE permission void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList, out int[] switches, out List<IBinder> binders); - void onPanelRevealed(boolean clearNotificationEffects); + void onPanelRevealed(boolean clearNotificationEffects, int numItems); void onPanelHidden(); // Mark current notifications as "seen" and stop ringing, vibrating, blinking. void clearNotificationEffects(); diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java index c869722..b2699f8 100644 --- a/core/java/com/android/internal/view/FloatingActionMode.java +++ b/core/java/com/android/internal/view/FloatingActionMode.java @@ -167,6 +167,7 @@ public class FloatingActionMode extends ActionMode { // Content rect is moving. mOriginatingView.removeCallbacks(mMovingOff); mFloatingToolbarVisibilityHelper.setMoving(true); + mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY); mFloatingToolbar.setContentRect(mContentRectOnWindow); @@ -174,9 +175,9 @@ public class FloatingActionMode extends ActionMode { } } else { mFloatingToolbarVisibilityHelper.setOutOfBounds(true); + mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); mContentRectOnWindow.setEmpty(); } - mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); mPreviousContentRectOnWindow.set(mContentRectOnWindow); } diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 3b1f20d..08d4e86 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -593,7 +593,7 @@ public final class MenuItemImpl implements MenuItem { public MenuItem setActionProvider(ActionProvider actionProvider) { if (mActionProvider != null) { - mActionProvider.setVisibilityListener(null); + mActionProvider.reset(); } mActionView = null; mActionProvider = actionProvider; diff --git a/core/java/com/android/internal/widget/DrawingSpace.java b/core/java/com/android/internal/widget/DrawingSpace.java new file mode 100644 index 0000000..b8222db --- /dev/null +++ b/core/java/com/android/internal/widget/DrawingSpace.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +/** + * Implementation of {@link android.widget.Space} that uses normal View drawing + * rather than a no-op. Useful for dialogs and other places where the base View + * class is too greedy when measured with AT_MOST. + */ +public final class DrawingSpace extends View { + public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public DrawingSpace(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DrawingSpace(Context context) { + this(context, null); + } + + /** + * Compare to: {@link View#getDefaultSize(int, int)} + * <p> + * If mode is AT_MOST, return the child size instead of the parent size + * (unless it is too big). + */ + private static int getDefaultSizeNonGreedy(int size, int measureSpec) { + int result = size; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + switch (specMode) { + case MeasureSpec.UNSPECIFIED: + result = size; + break; + case MeasureSpec.AT_MOST: + result = Math.min(size, specSize); + break; + case MeasureSpec.EXACTLY: + result = specSize; + break; + } + return result; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension( + getDefaultSizeNonGreedy(getSuggestedMinimumWidth(), widthMeasureSpec), + getDefaultSizeNonGreedy(getSuggestedMinimumHeight(), heightMeasureSpec)); + } +} diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 163b8ce..a6e8034 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -1135,7 +1135,7 @@ public final class FloatingToolbar { private final Runnable mCloseOverflow; private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener; - private int mOverflowWidth = 0; + private int mOverflowWidth; private int mSuggestedHeight; /** @@ -1146,7 +1146,6 @@ public final class FloatingToolbar { */ public FloatingToolbarOverflowPanel(Context context, Runnable closeOverflow) { mCloseOverflow = Preconditions.checkNotNull(closeOverflow); - mSuggestedHeight = getScreenHeight(context); mContentView = new LinearLayout(context); mContentView.setOrientation(LinearLayout.VERTICAL); @@ -1270,7 +1269,8 @@ public final class FloatingToolbar { mListView.setLayoutParams(params); } - private int setOverflowWidth() { + private void setOverflowWidth() { + mOverflowWidth = 0; for (int i = 0; i < mListView.getAdapter().getCount(); i++) { MenuItem menuItem = (MenuItem) mListView.getAdapter().getItem(i); Preconditions.checkNotNull(menuItem); @@ -1280,7 +1280,6 @@ public final class FloatingToolbar { mOverflowWidth = Math.max( mListViewItemWidthCalculator.getMeasuredWidth(), mOverflowWidth); } - return mOverflowWidth; } private ListView createOverflowListView() { @@ -1505,18 +1504,4 @@ public final class FloatingToolbar { return context.getResources() .getDimensionPixelSize(R.dimen.floating_toolbar_menu_button_minimum_width); } - - /** - * Returns the device's screen width. - */ - private static int getScreenWidth(Context context) { - return context.getResources().getDisplayMetrics().widthPixels; - } - - /** - * Returns the device's screen height. - */ - private static int getScreenHeight(Context context) { - return context.getResources().getDisplayMetrics().heightPixels; - } } diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index f7cfe0e..db88962 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -20,9 +20,13 @@ #include <sys/mount.h> #include <linux/fs.h> +#include <list> +#include <string> + #include <fcntl.h> #include <grp.h> #include <inttypes.h> +#include <mntent.h> #include <paths.h> #include <signal.h> #include <stdlib.h> @@ -249,6 +253,34 @@ static void SetSchedulerPolicy(JNIEnv* env) { } } +static int UnmountTree(const char* path) { + size_t path_len = strlen(path); + + FILE* fp = setmntent("/proc/mounts", "r"); + if (fp == NULL) { + ALOGE("Error opening /proc/mounts: %s", strerror(errno)); + return -errno; + } + + // Some volumes can be stacked on each other, so force unmount in + // reverse order to give us the best chance of success. + std::list<std::string> toUnmount; + mntent* mentry; + while ((mentry = getmntent(fp)) != NULL) { + if (strncmp(mentry->mnt_dir, path, path_len) == 0) { + toUnmount.push_front(std::string(mentry->mnt_dir)); + } + } + endmntent(fp); + + for (auto path : toUnmount) { + if (umount2(path.c_str(), MNT_DETACH)) { + ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno)); + } + } + return 0; +} + // Create a private mount namespace and bind mount appropriate emulated // storage for the given user. static bool MountEmulatedStorage(uid_t uid, jint mount_mode, @@ -262,7 +294,7 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode, } // Unmount storage provided by root namespace and mount requested view - umount2("/storage", MNT_FORCE); + UnmountTree("/storage"); String8 storageSource; if (mount_mode == MOUNT_EXTERNAL_DEFAULT) { @@ -281,7 +313,7 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode, return false; } - // Mount user-specific symlink helpers into place + // Mount user-specific symlink helper into place userid_t user_id = multiuser_get_user_id(uid); const String8 userSource(String8::format("/mnt/user/%d", user_id)); if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index bada791..7f61a04 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1024,15 +1024,6 @@ <!-- ================================== --> <eat-comment /> - <!-- Permissions for direct access to the accounts managed - by the Account Manager. --> - <permission-group android:name="android.permission-group.ACCOUNTS" - android:label="@string/permgrouplab_accounts" - android:icon="@drawable/perm_group_accounts" - android:description="@string/permgroupdesc_accounts" - android:permissionGroupFlags="personalInfo" - android:priority="1000" /> - <!-- Allows access to the list of accounts in the Accounts Service. <p>Protection level: normal --> @@ -1045,7 +1036,6 @@ <!-- @SystemApi Allows applications to call into AccountAuthenticators. <p>Not for use by third-party applications. --> <permission android:name="android.permission.ACCOUNT_MANAGER" - android:permissionGroup="android.permission-group.ACCOUNTS" android:protectionLevel="signature" /> <!-- ================================== --> @@ -1414,7 +1404,7 @@ <permission android:name="android.permission.SYSTEM_ALERT_WINDOW" android:label="@string/permlab_systemAlertWindow" android:description="@string/permdesc_systemAlertWindow" - android:protectionLevel="dangerous" /> + android:protectionLevel="signature|system|appop" /> <!-- ================================== --> <!-- Permissions affecting the system wallpaper --> diff --git a/core/res/res/drawable-hdpi/perm_group_accounts.png b/core/res/res/drawable-hdpi/perm_group_accounts.png Binary files differdeleted file mode 100644 index 5ac28e7..0000000 --- a/core/res/res/drawable-hdpi/perm_group_accounts.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/perm_group_accounts.png b/core/res/res/drawable-mdpi/perm_group_accounts.png Binary files differdeleted file mode 100644 index ce4e683..0000000 --- a/core/res/res/drawable-mdpi/perm_group_accounts.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/perm_group_accounts.png b/core/res/res/drawable-xhdpi/perm_group_accounts.png Binary files differdeleted file mode 100644 index ca622e9..0000000 --- a/core/res/res/drawable-xhdpi/perm_group_accounts.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_accounts.png b/core/res/res/drawable-xxhdpi/ic_perm_group_accounts.png Binary files differdeleted file mode 100644 index f30fcd4..0000000 --- a/core/res/res/drawable-xxhdpi/ic_perm_group_accounts.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_storage.png b/core/res/res/drawable-xxhdpi/ic_perm_group_storage.png Binary files differdeleted file mode 100644 index d3937db..0000000 --- a/core/res/res/drawable-xxhdpi/ic_perm_group_storage.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/perm_group_accounts.png b/core/res/res/drawable-xxhdpi/perm_group_accounts.png Binary files differdeleted file mode 100644 index 2fc3baa..0000000 --- a/core/res/res/drawable-xxhdpi/perm_group_accounts.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/perm_group_accounts.png b/core/res/res/drawable-xxxhdpi/perm_group_accounts.png Binary files differdeleted file mode 100644 index 1d9db83..0000000 --- a/core/res/res/drawable-xxxhdpi/perm_group_accounts.png +++ /dev/null diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml index 65da1f1..62131da 100644 --- a/core/res/res/drawable/perm_group_storage.xml +++ b/core/res/res/drawable/perm_group_storage.xml @@ -16,9 +16,12 @@ Copyright (C) 2015 The Android Open Source Project <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" - android:viewportWidth="48.0" - android:viewportHeight="48.0"> + android:viewportWidth="24.0" + android:viewportHeight="24.0"> <path - android:pathData="M20,8H8c-2.2,0 -4,1.8 -4,4l0,24c0,2.2 1.8,4 4,4h32c2.2,0 4,-1.8 4,-4V16c0,-2.2 -1.8,-4 -4,-4H24L20,8z" - android:fillColor="#FFFFFF"/> + android:fillColor="#FF000000" + android:pathData="M0,0h48v48H0z"/> + <path + android:fillColor="#FF000000" + android:pathData="M27,9c2.2,0 4,-1.8 4,-4s-1.8,-4 -4,-4 -4,1.8 -4,4 1.8,4 4,4zm-7.2,27.8l1.9,-8.8 4.3,4v12h4V28.9l-4.1,-4.1 1.2,-6C29.7,22 33.6,24 38,24v-4c-3.7,0 -6.9,-2 -8.7,-4.9l-1.9,-3.2c-0.7,-1.2 -2,-1.9 -3.4,-1.9 -0.5,0 -1,0.1 -1.5,0.3L12,14.6V24h4v-6.7l3.5,-1.4L16.4,32l-9.8,-1.9 -0.8,3.9s14,2.7 14,2.8z"/> </vector> diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml index 2fa2054..2473e87 100644 --- a/core/res/res/layout-land/time_picker_material.xml +++ b/core/res/res/layout-land/time_picker_material.xml @@ -21,7 +21,7 @@ android:layoutDirection="ltr"> <!-- Provides a background for the time layout that extends into the button bar area. --> - <View + <com.android.internal.widget.DrawingSpace android:id="@+id/time_header" android:layout_width="0dp" android:layout_height="wrap_content" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index fd47d49..b1925ba 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3124,6 +3124,8 @@ i <flag name="typeWindowsChanged" value="0x00400000" /> <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CONTEXT_CLICKED} events. --> <flag name="typeContextClicked" value="0x00800000" /> + <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_ASSIST_READING_CONTEXT} events. --> + <flag name="typeAssistReadingContext" value="0x01000000" /> <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. --> <flag name="typeAllMask" value="0xffffffff" /> </attr> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 4bc2205..451813c 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2258,4 +2258,7 @@ <!-- Flag indicating device support for EAP SIM, AKA, AKA' --> <bool name="config_eap_sim_based_auth_supported">true</bool> + + <!-- How long history of previous vibrations should be kept for the dumpsys. --> + <integer name="config_previousVibrationsDumpLimit">20</integer> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 5288fa3..bf6b015 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -676,11 +676,6 @@ Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received.</string> - <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permgrouplab_accounts">Your accounts</string> - <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permgroupdesc_accounts">Access the available accounts.</string> - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_subscribedFeedsRead">read subscribed feeds</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index ebbbc4c..01ecba8 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1708,6 +1708,7 @@ <java-symbol type="integer" name="config_notificationsBatteryLowARGB" /> <java-symbol type="integer" name="config_notificationsBatteryMediumARGB" /> <java-symbol type="integer" name="config_notificationServiceArchiveSize" /> + <java-symbol type="integer" name="config_previousVibrationsDumpLimit" /> <java-symbol type="integer" name="config_radioScanningTimeout" /> <java-symbol type="integer" name="config_screenBrightnessSettingMinimum" /> <java-symbol type="integer" name="config_screenBrightnessSettingMaximum" /> diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java index 5c55efb..ea444a4 100644 --- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java +++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java @@ -16,6 +16,8 @@ package android.net; +import android.net.IpPrefix; +import android.net.LinkAddress; import android.net.LinkProperties; import android.net.LinkProperties.ProvisioningChange; import android.net.RouteInfo; @@ -26,6 +28,7 @@ import junit.framework.TestCase; import java.net.InetAddress; import java.util.ArrayList; + public class LinkPropertiesTest extends TestCase { private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1"); private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress( @@ -567,4 +570,80 @@ public class LinkPropertiesTest extends TestCase { assertEquals(ProvisioningChange.STILL_PROVISIONED, LinkProperties.compareProvisioning(v6lp, v6lp2)); } + + @SmallTest + public void testIsReachable() { + final LinkProperties v4lp = new LinkProperties(); + assertFalse(v4lp.isReachable(DNS1)); + assertFalse(v4lp.isReachable(DNS2)); + + // Add an on-link route, making the on-link DNS server reachable, + // but there is still no IPv4 address. + assertTrue(v4lp.addRoute(new RouteInfo( + new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16)))); + assertFalse(v4lp.isReachable(DNS1)); + assertFalse(v4lp.isReachable(DNS2)); + + // Adding an IPv4 address (right now, any IPv4 address) means we use + // the routes to compute likely reachability. + assertTrue(v4lp.addLinkAddress(new LinkAddress(ADDRV4, 16))); + assertTrue(v4lp.isReachable(DNS1)); + assertFalse(v4lp.isReachable(DNS2)); + + // Adding a default route makes the off-link DNS server reachable. + assertTrue(v4lp.addRoute(new RouteInfo(GATEWAY1))); + assertTrue(v4lp.isReachable(DNS1)); + assertTrue(v4lp.isReachable(DNS2)); + + final LinkProperties v6lp = new LinkProperties(); + final InetAddress kLinkLocalDns = NetworkUtils.numericToInetAddress("fe80::6:1"); + final InetAddress kLinkLocalDnsWithScope = NetworkUtils.numericToInetAddress("fe80::6:2%43"); + final InetAddress kOnLinkDns = NetworkUtils.numericToInetAddress("2001:db8:85a3::53"); + assertFalse(v6lp.isReachable(kLinkLocalDns)); + assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope)); + assertFalse(v6lp.isReachable(kOnLinkDns)); + assertFalse(v6lp.isReachable(DNS6)); + + // Add a link-local route, making the link-local DNS servers reachable. Because + // we assume the presence of an IPv6 link-local address, link-local DNS servers + // are considered reachable, but only those with a non-zero scope identifier. + assertTrue(v6lp.addRoute(new RouteInfo( + new IpPrefix(NetworkUtils.numericToInetAddress("fe80::"), 64)))); + assertFalse(v6lp.isReachable(kLinkLocalDns)); + assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); + assertFalse(v6lp.isReachable(kOnLinkDns)); + assertFalse(v6lp.isReachable(DNS6)); + + // Add a link-local address--nothing changes. + assertTrue(v6lp.addLinkAddress(LINKADDRV6LINKLOCAL)); + assertFalse(v6lp.isReachable(kLinkLocalDns)); + assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); + assertFalse(v6lp.isReachable(kOnLinkDns)); + assertFalse(v6lp.isReachable(DNS6)); + + // Add a global route on link, but no global address yet. DNS servers reachable + // via a route that doesn't require a gateway: give them the benefit of the + // doubt and hope the link-local source address suffices for communication. + assertTrue(v6lp.addRoute(new RouteInfo( + new IpPrefix(NetworkUtils.numericToInetAddress("2001:db8:85a3::"), 64)))); + assertFalse(v6lp.isReachable(kLinkLocalDns)); + assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); + assertTrue(v6lp.isReachable(kOnLinkDns)); + assertFalse(v6lp.isReachable(DNS6)); + + // Add a global address; the on-link global address DNS server is (still) + // presumed reachable. + assertTrue(v6lp.addLinkAddress(new LinkAddress(ADDRV6, 64))); + assertFalse(v6lp.isReachable(kLinkLocalDns)); + assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); + assertTrue(v6lp.isReachable(kOnLinkDns)); + assertFalse(v6lp.isReachable(DNS6)); + + // Adding a default route makes the off-link DNS server reachable. + assertTrue(v6lp.addRoute(new RouteInfo(GATEWAY62))); + assertFalse(v6lp.isReachable(kLinkLocalDns)); + assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); + assertTrue(v6lp.isReachable(kOnLinkDns)); + assertTrue(v6lp.isReachable(DNS6)); + } } diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java index a50fb54..31a4703 100644 --- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java +++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java @@ -51,11 +51,15 @@ public class InputMethodTest extends InstrumentationTestCase { private static final Locale LOCALE_FR = new Locale("fr"); private static final Locale LOCALE_FR_CA = new Locale("fr", "CA"); private static final Locale LOCALE_HI = new Locale("hi"); + private static final Locale LOCALE_JA = new Locale("ja"); private static final Locale LOCALE_JA_JP = new Locale("ja", "JP"); private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN"); private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW"); private static final Locale LOCALE_IN = new Locale("in"); private static final Locale LOCALE_ID = new Locale("id"); + private static final Locale LOCALE_TH = new Locale("ht"); + private static final Locale LOCALE_TH_TH = new Locale("ht", "TH"); + private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH"); private static final String SUBTYPE_MODE_KEYBOARD = "keyboard"; private static final String SUBTYPE_MODE_VOICE = "voice"; private static final String SUBTYPE_MODE_ANY = null; @@ -849,4 +853,99 @@ public class InputMethodTest extends InstrumentationTestCase { return preinstalledImes; } + + @SmallTest + public void testGetSuitableLocalesForSpellChecker() throws Exception { + { + final ArrayList<Locale> locales = + InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_US); + assertEquals(3, locales.size()); + assertEquals(LOCALE_EN_US, locales.get(0)); + assertEquals(LOCALE_EN_GB, locales.get(1)); + assertEquals(LOCALE_EN, locales.get(2)); + } + + { + final ArrayList<Locale> locales = + InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_GB); + assertEquals(3, locales.size()); + assertEquals(LOCALE_EN_GB, locales.get(0)); + assertEquals(LOCALE_EN_US, locales.get(1)); + assertEquals(LOCALE_EN, locales.get(2)); + } + + { + final ArrayList<Locale> locales = + InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN); + assertEquals(3, locales.size()); + assertEquals(LOCALE_EN, locales.get(0)); + assertEquals(LOCALE_EN_US, locales.get(1)); + assertEquals(LOCALE_EN_GB, locales.get(2)); + } + + { + final ArrayList<Locale> locales = + InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_IN); + assertEquals(4, locales.size()); + assertEquals(LOCALE_EN_IN, locales.get(0)); + assertEquals(LOCALE_EN_US, locales.get(1)); + assertEquals(LOCALE_EN_GB, locales.get(2)); + assertEquals(LOCALE_EN, locales.get(3)); + } + + { + final ArrayList<Locale> locales = + InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_JA_JP); + assertEquals(5, locales.size()); + assertEquals(LOCALE_JA_JP, locales.get(0)); + assertEquals(LOCALE_JA, locales.get(1)); + assertEquals(LOCALE_EN_US, locales.get(2)); + assertEquals(LOCALE_EN_GB, locales.get(3)); + assertEquals(Locale.ENGLISH, locales.get(4)); + } + + // Test 3-letter language code. + { + final ArrayList<Locale> locales = + InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_FIL_PH); + assertEquals(5, locales.size()); + assertEquals(LOCALE_FIL_PH, locales.get(0)); + assertEquals(LOCALE_FIL, locales.get(1)); + assertEquals(LOCALE_EN_US, locales.get(2)); + assertEquals(LOCALE_EN_GB, locales.get(3)); + assertEquals(Locale.ENGLISH, locales.get(4)); + } + + // Test variant. + { + final ArrayList<Locale> locales = + InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_TH_TH_TH); + assertEquals(6, locales.size()); + assertEquals(LOCALE_TH_TH_TH, locales.get(0)); + assertEquals(LOCALE_TH_TH, locales.get(1)); + assertEquals(LOCALE_TH, locales.get(2)); + assertEquals(LOCALE_EN_US, locales.get(3)); + assertEquals(LOCALE_EN_GB, locales.get(4)); + assertEquals(Locale.ENGLISH, locales.get(5)); + } + + // Test Locale extension. + { + final Locale localeWithoutVariant = LOCALE_JA_JP; + final Locale localeWithVariant = new Locale.Builder() + .setLocale(LOCALE_JA_JP) + .setExtension('x', "android") + .build(); + assertFalse(localeWithoutVariant.equals(localeWithVariant)); + + final ArrayList<Locale> locales = + InputMethodUtils.getSuitableLocalesForSpellChecker(localeWithVariant); + assertEquals(5, locales.size()); + assertEquals(LOCALE_JA_JP, locales.get(0)); + assertEquals(LOCALE_JA, locales.get(1)); + assertEquals(LOCALE_EN_US, locales.get(2)); + assertEquals(LOCALE_EN_GB, locales.get(3)); + assertEquals(Locale.ENGLISH, locales.get(4)); + } + } } |
