diff options
120 files changed, 2580 insertions, 1072 deletions
diff --git a/Android.mk b/Android.mk index 7c9397fc218c..8c0c640f2764 100644 --- a/Android.mk +++ b/Android.mk @@ -108,6 +108,7 @@ LOCAL_SRC_FILES += \ core/java/android/app/backup/IFullBackupRestoreObserver.aidl \ core/java/android/app/backup/IRestoreObserver.aidl \ core/java/android/app/backup/IRestoreSession.aidl \ + core/java/android/app/usage/IStorageStatsManager.aidl \ core/java/android/app/usage/IUsageStatsManager.aidl \ core/java/android/bluetooth/IBluetooth.aidl \ core/java/android/bluetooth/IBluetoothA2dp.aidl \ @@ -689,6 +690,8 @@ aidl_files := \ frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \ frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \ frameworks/base/core/java/android/speech/tts/Voice.aidl \ + frameworks/base/core/java/android/app/usage/StorageStats.aidl \ + frameworks/base/core/java/android/app/usage/StorageSummary.aidl \ frameworks/base/core/java/android/app/usage/UsageEvents.aidl \ frameworks/base/core/java/android/app/Notification.aidl \ frameworks/base/core/java/android/app/NotificationManager.aidl \ diff --git a/api/current.txt b/api/current.txt index b58947d36c0b..a8cdd10772b1 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5393,7 +5393,6 @@ package android.app { method public android.net.Uri getSound(); method public long[] getVibrationPattern(); method public boolean isAllowed(); - method public void setAllowed(boolean); method public void setBypassDnd(boolean); method public void setImportance(int); method public void setLights(boolean); @@ -6679,6 +6678,36 @@ package android.app.usage { method public abstract void onThresholdReached(int, java.lang.String); } + public final class StorageStats implements android.os.Parcelable { + method public int describeContents(); + method public long getCacheBytes(); + method public long getCacheQuotaBytes(); + method public long getCodeBytes(); + method public long getDataBytes(); + method public int getUid(); + method public java.lang.String getVolumeUuid(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; + } + + public class StorageStatsManager { + method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int); + method public android.app.usage.StorageSummary querySummary(java.lang.String); + } + + public final class StorageSummary implements android.os.Parcelable { + method public int describeContents(); + method public long getFreeBytes(); + method public long getSharedAudioBytes(); + method public long getSharedImagesBytes(); + method public long getSharedTotalBytes(); + method public long getSharedVideoBytes(); + method public long getTotalBytes(); + method public java.lang.String getVolumeUuid(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.usage.StorageSummary> CREATOR; + } + public final class UsageEvents implements android.os.Parcelable { method public int describeContents(); method public boolean getNextEvent(android.app.usage.UsageEvents.Event); @@ -8415,6 +8444,7 @@ package android.content { field public static final java.lang.String SENSOR_SERVICE = "sensor"; field public static final java.lang.String SHORTCUT_SERVICE = "shortcut"; field public static final java.lang.String STORAGE_SERVICE = "storage"; + field public static final java.lang.String STORAGE_STATS_SERVICE = "storagestats"; field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth"; field public static final java.lang.String TELECOM_SERVICE = "telecom"; field public static final java.lang.String TELEPHONY_SERVICE = "phone"; @@ -11949,8 +11979,6 @@ package android.graphics { method public boolean clipRect(float, float, float, float, android.graphics.Region.Op); method public boolean clipRect(float, float, float, float); method public boolean clipRect(int, int, int, int); - method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op); - method public deprecated boolean clipRegion(android.graphics.Region); method public void concat(android.graphics.Matrix); method public void drawARGB(int, int, int, int); method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint); diff --git a/api/removed.txt b/api/removed.txt index 35b485980276..d7a8bce2d00b 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -78,6 +78,11 @@ package android.graphics { enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; } + public class Canvas { + method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op); + method public deprecated boolean clipRegion(android.graphics.Region); + } + public deprecated class LayerRasterizer extends android.graphics.Rasterizer { ctor public LayerRasterizer(); method public void addLayer(android.graphics.Paint, float, float); diff --git a/api/system-current.txt b/api/system-current.txt index b9125e57e4f0..14a767ba038c 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5555,7 +5555,6 @@ package android.app { method public boolean isAllowed(); method public void lockFields(int); method public void populateFromXml(org.xmlpull.v1.XmlPullParser); - method public void setAllowed(boolean); method public void setBypassDnd(boolean); method public void setImportance(int); method public void setLights(boolean); @@ -6992,6 +6991,36 @@ package android.app.usage { method public abstract void onThresholdReached(int, java.lang.String); } + public final class StorageStats implements android.os.Parcelable { + method public int describeContents(); + method public long getCacheBytes(); + method public long getCacheQuotaBytes(); + method public long getCodeBytes(); + method public long getDataBytes(); + method public int getUid(); + method public java.lang.String getVolumeUuid(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; + } + + public class StorageStatsManager { + method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int); + method public android.app.usage.StorageSummary querySummary(java.lang.String); + } + + public final class StorageSummary implements android.os.Parcelable { + method public int describeContents(); + method public long getFreeBytes(); + method public long getSharedAudioBytes(); + method public long getSharedImagesBytes(); + method public long getSharedTotalBytes(); + method public long getSharedVideoBytes(); + method public long getTotalBytes(); + method public java.lang.String getVolumeUuid(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.usage.StorageSummary> CREATOR; + } + public final class UsageEvents implements android.os.Parcelable { method public int describeContents(); method public boolean getNextEvent(android.app.usage.UsageEvents.Event); @@ -8770,6 +8799,7 @@ package android.content { field public static final java.lang.String SENSOR_SERVICE = "sensor"; field public static final java.lang.String SHORTCUT_SERVICE = "shortcut"; field public static final java.lang.String STORAGE_SERVICE = "storage"; + field public static final java.lang.String STORAGE_STATS_SERVICE = "storagestats"; field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth"; field public static final java.lang.String TELECOM_SERVICE = "telecom"; field public static final java.lang.String TELEPHONY_SERVICE = "phone"; @@ -12447,8 +12477,6 @@ package android.graphics { method public boolean clipRect(float, float, float, float, android.graphics.Region.Op); method public boolean clipRect(float, float, float, float); method public boolean clipRect(int, int, int, int); - method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op); - method public deprecated boolean clipRegion(android.graphics.Region); method public void concat(android.graphics.Matrix); method public void drawARGB(int, int, int, int); method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint); diff --git a/api/system-removed.txt b/api/system-removed.txt index 8016f58ccedb..7ba88bdb9d33 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -76,6 +76,11 @@ package android.graphics { enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; } + public class Canvas { + method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op); + method public deprecated boolean clipRegion(android.graphics.Region); + } + public deprecated class LayerRasterizer extends android.graphics.Rasterizer { ctor public LayerRasterizer(); method public void addLayer(android.graphics.Paint, float, float); diff --git a/api/test-current.txt b/api/test-current.txt index 4118053af2f7..e6148835639f 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -5403,7 +5403,6 @@ package android.app { method public android.net.Uri getSound(); method public long[] getVibrationPattern(); method public boolean isAllowed(); - method public void setAllowed(boolean); method public void setBypassDnd(boolean); method public void setImportance(int); method public void setLights(boolean); @@ -6701,6 +6700,36 @@ package android.app.usage { method public abstract void onThresholdReached(int, java.lang.String); } + public final class StorageStats implements android.os.Parcelable { + method public int describeContents(); + method public long getCacheBytes(); + method public long getCacheQuotaBytes(); + method public long getCodeBytes(); + method public long getDataBytes(); + method public int getUid(); + method public java.lang.String getVolumeUuid(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; + } + + public class StorageStatsManager { + method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int); + method public android.app.usage.StorageSummary querySummary(java.lang.String); + } + + public final class StorageSummary implements android.os.Parcelable { + method public int describeContents(); + method public long getFreeBytes(); + method public long getSharedAudioBytes(); + method public long getSharedImagesBytes(); + method public long getSharedTotalBytes(); + method public long getSharedVideoBytes(); + method public long getTotalBytes(); + method public java.lang.String getVolumeUuid(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.usage.StorageSummary> CREATOR; + } + public final class UsageEvents implements android.os.Parcelable { method public int describeContents(); method public boolean getNextEvent(android.app.usage.UsageEvents.Event); @@ -8439,6 +8468,7 @@ package android.content { field public static final java.lang.String SENSOR_SERVICE = "sensor"; field public static final java.lang.String SHORTCUT_SERVICE = "shortcut"; field public static final java.lang.String STORAGE_SERVICE = "storage"; + field public static final java.lang.String STORAGE_STATS_SERVICE = "storagestats"; field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth"; field public static final java.lang.String TELECOM_SERVICE = "telecom"; field public static final java.lang.String TELEPHONY_SERVICE = "phone"; @@ -11980,8 +12010,6 @@ package android.graphics { method public boolean clipRect(float, float, float, float, android.graphics.Region.Op); method public boolean clipRect(float, float, float, float); method public boolean clipRect(int, int, int, int); - method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op); - method public deprecated boolean clipRegion(android.graphics.Region); method public void concat(android.graphics.Matrix); method public void drawARGB(int, int, int, int); method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint); diff --git a/api/test-removed.txt b/api/test-removed.txt index 35b485980276..d7a8bce2d00b 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -78,6 +78,11 @@ package android.graphics { enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; } + public class Canvas { + method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op); + method public deprecated boolean clipRegion(android.graphics.Region); + } + public deprecated class LayerRasterizer extends android.graphics.Rasterizer { ctor public LayerRasterizer(); method public void addLayer(android.graphics.Paint, float, float); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 8185818ccd29..2be84c14cce6 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -328,7 +328,6 @@ public class AccountManager { /** * Token type for the special case where a UID has access only to an account * but no authenticator specific auth token types. - * * @hide */ public static final String ACCOUNT_ACCESS_TOKEN_TYPE = @@ -354,9 +353,9 @@ public class AccountManager { * the applications are added, accounts are removed, or an account's credentials (saved * password, etc) are changed. List of supported account types shoud be specified in the * Manifest file using {@link #SUPPORTED_ACCOUNT_TYPES} - * - * @see #addOnAccountsUpdatedListener * @hide + * @see #addOnAccountsUpdatedListener + * */ public static final String ACTION_VISIBLE_ACCOUNTS_CHANGED = "android.accounts.action.VISIBLE_ACCOUNTS_CHANGED"; @@ -364,6 +363,7 @@ public class AccountManager { /** * Authenticators may subscribe to get notifications about apps interested in their managed account * types using {@link #SUPPORTED_ACCOUNT_TYPES}. + * Package name will be specified using {@link Intent.EXTRA_PACKAGE_NAME} * @hide */ public static final String ACTION_ACCOUNTS_LISTENER_PACKAGE_INSTALLED = @@ -1024,7 +1024,7 @@ public class AccountManager { public boolean isAccountVisible(Account account, int uid) { try { Integer visibility = mService.getAccountVisibility(account, uid); - return visibility == VISIBILITY_USER_MANAGED_NOT_VISIBLE + return visibility == VISIBILITY_USER_MANAGED_VISIBLE || visibility == VISIBILITY_VISIBLE; } catch (RemoteException re) { throw re.rethrowFromSystemServer(); @@ -1058,6 +1058,7 @@ public class AccountManager { /** * Gets visibility of certain account for given UID. Possible returned values are: * <ul> + * <li>{@link #VISIBILITY_UNDEFINED}</li> * <li>{@link #VISIBILITY_VISIBLE}</li> * <li>{@link #VISIBILITY_USER_MANAGED_VISIBLE}</li> * <li>{@link #VISIBILITY_NOT_VISIBLE} diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java index 242b3ea3306e..16a45ba6d5fe 100644 --- a/core/java/android/accounts/ChooseAccountActivity.java +++ b/core/java/android/accounts/ChooseAccountActivity.java @@ -52,7 +52,9 @@ public class ChooseAccountActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + // TODO This activity is only used by getAuthTokenByFeatures and can not see + // VISIBILITY_USER_MANAGED_NOT_VISIBLE accounts. It should be moved to account managed + // service. mAccounts = getIntent().getParcelableArrayExtra(AccountManager.KEY_ACCOUNTS); mAccountManagerResponse = getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 761da35f3607..cd50c4dbec15 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -80,7 +80,39 @@ import java.util.ArrayList; import java.util.List; /** - * Interact with the overall activities running in the system. + * <p> + * This class gives information about, and interacts + * with, activities, services, and the containing + * process. + * </p> + * + * <p> + * A number of the methods in this class are for + * debugging or informational purposes and they should + * not be used to affect any runtime behavior of + * your app. These methods are called out as such in + * the method level documentation. + * </p> + * + *<p> + * Most application developers should not have the need to + * use this class, most of whose methods are for specialized + * use cases. However, a few methods are more broadly applicable. + * For instance, {@link android.app.ActivityManager#isLowRamDevice() isLowRamDevice()} + * enables your app to detect whether it is running on a low-memory device, + * and behave accordingly. + * {@link android.app.ActivityManager#clearApplicationUserData() clearApplicationUserData()} + * is for apps with reset-data functionality. + * </p> + * + * <p> + * In some special use cases, where an app interacts with + * its Task stack, the app may use the + * {@link android.app.ActivityManager.AppTask} and + * {@link android.app.ActivityManager.RecentTaskInfo} inner + * classes. However, in general, the methods in this class should + * be used for testing and debugging purposes only. + * </p> */ public class ActivityManager { private static String TAG = "ActivityManager"; diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 627391764069..bdccb8a9620c 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -55,7 +55,6 @@ public final class NotificationChannel implements Parcelable { private static final String ATT_AUDIO_ATTRIBUTES = "audio_attributes"; private static final String ATT_SHOW_BADGE = "show_badge"; private static final String ATT_USER_LOCKED = "locked"; - private static final String ATT_ALLOWED = "allowed"; private static final String DELIMITER = ","; /** @@ -243,18 +242,6 @@ public final class NotificationChannel implements Parcelable { this.mImportance = importance; } - /** - * Sets whether notifications are allowed to be posted to this channel. - * - * Only modifiable by the system and notification ranker. - * - * @param allowed true if notifications are not allowed from this channel. - */ - public void setAllowed(boolean allowed) { - this.mAllowed = allowed; - } - - // Modifiable by apps on channel creation. /** @@ -406,7 +393,6 @@ public final class NotificationChannel implements Parcelable { enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false)); setVibrationPattern(safeLongArray(parser, ATT_VIBRATION, null)); setShowBadge(safeBool(parser, ATT_SHOW_BADGE, false)); - setAllowed(safeBool(parser, ATT_ALLOWED, true)); lockFields(safeInt(parser, ATT_USER_LOCKED, 0)); } @@ -448,9 +434,6 @@ public final class NotificationChannel implements Parcelable { if (canShowBadge()) { out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(canShowBadge())); } - if (!isAllowed()) { - out.attribute(null, ATT_ALLOWED, Boolean.toString(isAllowed())); - } out.endTag(null, TAG_CHANNEL); } @@ -481,8 +464,6 @@ public final class NotificationChannel implements Parcelable { record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields())); record.put(ATT_VIBRATION, longArrayToString(getVibrationPattern())); record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge())); - record.put(ATT_ALLOWED, Boolean.toString(isAllowed())); - return record; } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 6bddfba163d0..9387019bc651 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -23,8 +23,10 @@ import android.app.admin.IDevicePolicyManager; import android.app.job.IJobScheduler; import android.app.job.JobScheduler; import android.app.trust.TrustManager; +import android.app.usage.IStorageStatsManager; import android.app.usage.IUsageStatsManager; import android.app.usage.NetworkStatsManager; +import android.app.usage.StorageStatsManager; import android.app.usage.UsageStatsManager; import android.appwidget.AppWidgetManager; import android.bluetooth.BluetoothManager; @@ -434,6 +436,15 @@ final class SystemServiceRegistry { return new StorageManager(ctx, ctx.mMainThread.getHandler().getLooper()); }}); + registerService(Context.STORAGE_STATS_SERVICE, StorageStatsManager.class, + new CachedServiceFetcher<StorageStatsManager>() { + @Override + public StorageStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IStorageStatsManager service = IStorageStatsManager.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.STORAGE_STATS_SERVICE)); + return new StorageStatsManager(ctx, service); + }}); + registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class, new CachedServiceFetcher<TelephonyManager>() { @Override diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java index 20ddb77261a0..28704e636f19 100644 --- a/core/java/android/app/admin/SystemUpdatePolicy.java +++ b/core/java/android/app/admin/SystemUpdatePolicy.java @@ -19,10 +19,8 @@ package android.app.admin; import android.annotation.IntDef; import android.os.Parcel; import android.os.Parcelable; -import android.os.PersistableBundle; import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; @@ -49,25 +47,45 @@ public class SystemUpdatePolicy implements Parcelable { * Unknown policy type, used only internally. */ private static final int TYPE_UNKNOWN = -1; + /** * Install system update automatically as soon as one is available. */ public static final int TYPE_INSTALL_AUTOMATIC = 1; /** - * Install system update automatically within a daily maintenance window, for a maximum of 30 - * days. After the expiration the policy will no longer be effective and the system should - * revert back to its normal behavior as if no policy were set. The only exception is - * {@link #TYPE_INSTALL_AUTOMATIC} which should still take effect to install system update - * immediately. + * Install system update automatically within a daily maintenance window. An update can be + * delayed for a maximum of 30 days, after which the policy will no longer be effective and the + * system will revert back to its normal behavior as if no policy were set. + * + * <p>After this policy expires, resetting it to any policy other than + * {@link #TYPE_INSTALL_AUTOMATIC} will produce no effect, as the 30-day maximum delay has + * already been used up. + * The {@link #TYPE_INSTALL_AUTOMATIC} policy will still take effect to install the delayed + * system update immediately. + * + * <p>Re-applying this policy or changing it to {@link #TYPE_POSTPONE} within the 30-day period + * will <i>not</i> extend policy expiration. + * However, the expiration will be recalculated when a new system update is made available. */ public static final int TYPE_INSTALL_WINDOWED = 2; /** - * Incoming system update will be blocked for a maximum of 30 days, after which the system - * should revert back to its normal behavior as if no policy were set. The only exception is - * {@link #TYPE_INSTALL_AUTOMATIC} which should still take effect to install system update - * immediately. + * Incoming system updates (except for security updates) will be blocked for 30 days, after + * which the policy will no longer be effective and the system will revert back to its normal + * behavior as if no policy were set. + * <b>Note:</b> security updates (e.g. monthly security patches) will <i>not</i> be affected by + * this policy. + * + * <p>After this policy expires, resetting it to any policy other than + * {@link #TYPE_INSTALL_AUTOMATIC} will produce no effect, as the 30-day maximum delay has + * already been used up. + * The {@link #TYPE_INSTALL_AUTOMATIC} policy will still take effect to install the delayed + * system update immediately. + * + * <p>Re-applying this policy or changing it to {@link #TYPE_INSTALL_WINDOWED} within the 30-day + * period will <i>not</i> extend policy expiration. + * However, the expiration will be recalculated when a new system update is made available. */ public static final int TYPE_POSTPONE = 3; @@ -105,11 +123,12 @@ public class SystemUpdatePolicy implements Parcelable { /** * Create a policy object and set it to: new system update will only be installed automatically * when the system clock is inside a daily maintenance window. If the start and end times are - * the same, the window is considered to include the WHOLE 24 hours, that is, updates can - * install at any time. If the given window in invalid, a {@link IllegalArgumentException} will - * be thrown. If start time is later than end time, the window is considered spanning midnight, - * i.e. end time donates a time on the next day. The maintenance window will last for 30 days, - * after which the system should revert back to its normal behavior as if no policy were set. + * the same, the window is considered to include the <i>whole 24 hours</i>. That is, updates can + * install at any time. If the given window in invalid, an {@link IllegalArgumentException} + * will be thrown. If start time is later than end time, the window is considered spanning + * midnight (i.e. the end time denotes a time on the next day). The maintenance window will last + * for 30 days, after which the system will revert back to its normal behavior as if no policy + * were set. * * @param startTime the start of the maintenance window, measured as the number of minutes from * midnight in the device's local time. Must be in the range of [0, 1440). @@ -131,9 +150,12 @@ public class SystemUpdatePolicy implements Parcelable { /** * Create a policy object and set it to block installation for a maximum period of 30 days. - * After expiration the system should revert back to its normal behavior as if no policy were + * After expiration the system will revert back to its normal behavior as if no policy were * set. * + * <p><b>Note: </b> security updates (e.g. monthly security patches) will <i>not</i> be affected + * by this policy. + * * @see #TYPE_POSTPONE */ public static SystemUpdatePolicy createPostponeInstallPolicy() { diff --git a/core/java/android/app/usage/IStorageStatsManager.aidl b/core/java/android/app/usage/IStorageStatsManager.aidl new file mode 100644 index 000000000000..96125a17b3a6 --- /dev/null +++ b/core/java/android/app/usage/IStorageStatsManager.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 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.app.usage; + +import android.app.usage.StorageStats; +import android.app.usage.StorageSummary; + +/** {@hide} */ +interface IStorageStatsManager { + StorageStats queryStats(String volumeUuid, int uid, String callingPackage); + StorageSummary querySummary(String volumeUuid, String callingPackage); +} diff --git a/core/java/android/app/usage/StorageStats.aidl b/core/java/android/app/usage/StorageStats.aidl new file mode 100644 index 000000000000..fde62672905d --- /dev/null +++ b/core/java/android/app/usage/StorageStats.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 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.app.usage; + +parcelable StorageStats; diff --git a/core/java/android/app/usage/StorageStats.java b/core/java/android/app/usage/StorageStats.java new file mode 100644 index 000000000000..b2486d8c6b23 --- /dev/null +++ b/core/java/android/app/usage/StorageStats.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2017 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.app.usage; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Storage statistics for a single UID on a single storage volume. + * <p class="note"> + * Note: multiple packages using the same {@code sharedUserId} in their manifest + * will be merged into a single UID. + * </p> + * + * @see StorageStatsManager + */ +public final class StorageStats implements Parcelable { + /** {@hide} */ public final String volumeUuid; + /** {@hide} */ public final int uid; + + /** {@hide} */ public long codeBytes; + /** {@hide} */ public long dataBytes; + /** {@hide} */ public long cacheQuotaBytes; + /** {@hide} */ public long cacheBytes; + + /** + * Return the UUID of the storage volume that these statistics refer to. The + * value {@code null} indicates the default internal storage. + */ + public String getVolumeUuid() { + return volumeUuid; + } + + /** + * Return the UID that these statistics refer to. + * + * @see ApplicationInfo#uid + * @see PackageManager#getPackagesForUid(int) + */ + public int getUid() { + return uid; + } + + /** + * Return the size of all code associated with {@link #getUid()} on + * {@link #getVolumeUuid()}. This includes {@code APK} files and optimized + * compiler output. + * <p> + * If the primary shared storage location is also hosted on + * {@link #getVolumeUuid()} then this includes files stored under + * {@link Context#getObbDir()}. + * <p> + * Code is shared between all users on a multiuser device. + */ + public long getCodeBytes() { + return codeBytes; + } + + /** + * Return the size of all data associated with {@link #getUid()} on + * {@link #getVolumeUuid()}. This includes files stored under + * {@link Context#getDataDir()}, {@link Context#getCacheDir()}, + * {@link Context#getCodeCacheDir()}. + * <p> + * If the primary shared storage location is also hosted on + * {@link #getVolumeUuid()} then this includes files stored under + * {@link Context#getExternalFilesDir(String)} and + * {@link Context#getExternalCacheDir()}. + * <p> + * Data is isolated for each user on a multiuser device. + */ + public long getDataBytes() { + return dataBytes; + } + + /** + * Return the quota for cached data associated with {@link #getUid()} on + * {@link #getVolumeUuid()}. This quota value is calculated based on how + * frequently the user has interacted with the UID. + * <p> + * When clearing cached data, the system will first focus on packages whose + * cached data is larger than their allocated quota. + */ + public long getCacheQuotaBytes() { + return cacheQuotaBytes; + } + + /** + * Return the size of all cached data associated with {@link #getUid()} on + * {@link #getVolumeUuid()}. This includes files stored under + * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}. + * <p> + * If the primary shared storage location is also hosted on + * {@link #getVolumeUuid()} then this includes files stored under + * {@link Context#getExternalCacheDir()}. + * <p> + * Cached data is isolated for each user on a multiuser device. + */ + public long getCacheBytes() { + return cacheBytes; + } + + /** {@hide} */ + public StorageStats(String uuid, int uid) { + this.volumeUuid = uuid; + this.uid = uid; + } + + /** {@hide} */ + public StorageStats(Parcel in) { + this.volumeUuid = in.readString(); + this.uid = in.readInt(); + this.codeBytes = in.readLong(); + this.dataBytes = in.readLong(); + this.cacheQuotaBytes = in.readLong(); + this.cacheBytes = in.readLong(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(volumeUuid); + dest.writeInt(uid); + dest.writeLong(codeBytes); + dest.writeLong(dataBytes); + dest.writeLong(cacheQuotaBytes); + dest.writeLong(cacheBytes); + } + + public static final Creator<StorageStats> CREATOR = new Creator<StorageStats>() { + @Override + public StorageStats createFromParcel(Parcel in) { + return new StorageStats(in); + } + + @Override + public StorageStats[] newArray(int size) { + return new StorageStats[size]; + } + }; +} diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java new file mode 100644 index 000000000000..cdfbe0c0b82f --- /dev/null +++ b/core/java/android/app/usage/StorageStatsManager.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2017 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.app.usage; + +import android.annotation.WorkerThread; +import android.content.Context; +import android.os.RemoteException; + +import com.android.internal.util.Preconditions; + +/** + * Provides access to detailed storage statistics. + * <p class="note"> + * Note: this API requires the permission + * {@code android.permission.PACKAGE_USAGE_STATS}, which is a system-level + * permission that will not be granted to normal apps. However, declaring the + * permission expresses your intention to use this API and an end user can then + * choose to grant this permission through the Settings application. + * </p> + */ +public class StorageStatsManager { + private final Context mContext; + private final IStorageStatsManager mService; + + /** {@hide} */ + public StorageStatsManager(Context context, IStorageStatsManager service) { + mContext = Preconditions.checkNotNull(context); + mService = Preconditions.checkNotNull(service); + } + + /** + * Return detailed statistics for the a specific UID on the requested + * storage volume. + * <p> + * This method may take several seconds to calculate the requested values, + * so it should only be called from a worker thread. + * + * @param volumeUuid the UUID of the storage volume you're interested in, or + * {@code null} to specify the default internal storage. + * @param uid the UID you're interested in. + */ + @WorkerThread + public StorageStats queryStatsForUid(String volumeUuid, int uid) { + try { + return mService.queryStats(volumeUuid, uid, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Return summary statistics for the requested storage volume. + * <p> + * This method may take several seconds to calculate the requested values, + * so it should only be called from a worker thread. + * + * @param volumeUuid the UUID of the storage volume you're interested in, or + * {@code null} to specify the default internal storage. + */ + @WorkerThread + public StorageSummary querySummary(String volumeUuid) { + try { + return mService.querySummary(volumeUuid, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/core/java/android/app/usage/StorageSummary.aidl b/core/java/android/app/usage/StorageSummary.aidl new file mode 100644 index 000000000000..b20e025130e6 --- /dev/null +++ b/core/java/android/app/usage/StorageSummary.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 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.app.usage; + +parcelable StorageSummary; diff --git a/core/java/android/app/usage/StorageSummary.java b/core/java/android/app/usage/StorageSummary.java new file mode 100644 index 000000000000..e72c9ecd2e25 --- /dev/null +++ b/core/java/android/app/usage/StorageSummary.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2017 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.app.usage; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.File; + +/** + * Storage summary for a single storage volume. + * <p> + * When presenting this summary to users, the + * <p> + * Details for specific UIDs are available through {@link StorageStats}. + * + * @see StorageStatsManager + */ +public final class StorageSummary implements Parcelable { + /** {@hide} */ public final String volumeUuid; + + /** {@hide} */ public long totalBytes; + /** {@hide} */ public long freeBytes; + + /** {@hide} */ public long sharedTotalBytes; + /** {@hide} */ public long sharedAudioBytes; + /** {@hide} */ public long sharedVideoBytes; + /** {@hide} */ public long sharedImagesBytes; + + /** + * Return the UUID of the storage volume that these statistics refer to. The + * value {@code null} indicates the default internal storage. + */ + public String getVolumeUuid() { + return volumeUuid; + } + + /** + * Return the total size of the storage volume. + * <p> + * To reduce end user confusion, this value is the total storage size + * advertised in a retail environment, which is typically larger than the + * actual writable partition total size. + */ + public long getTotalBytes() { + return totalBytes; + } + + /** + * Return the free space on this storage volume. + * <p> + * The free space is equivalent to {@link File#getFreeSpace()} plus the size + * of any cached data that can be automatically deleted by the system as + * additional space is needed. + */ + public long getFreeBytes() { + return freeBytes; + } + + /** + * Return the total bytes used by all files in the shared storage hosted on + * this volume. + * + * @return total bytes, or {@code -1} if no shared storage is hosted on this + * volume. + */ + public long getSharedTotalBytes() { + return sharedTotalBytes; + } + + /** + * Return the total bytes used by audio files in the shared storage hosted + * on this volume. + * + * @return total bytes, or {@code -1} if no shared storage is hosted on this + * volume. + */ + public long getSharedAudioBytes() { + return sharedAudioBytes; + } + + /** + * Return the total bytes used by video files in the shared storage hosted + * on this volume. + * + * @return total bytes, or {@code -1} if no shared storage is hosted on this + * volume. + */ + public long getSharedVideoBytes() { + return sharedVideoBytes; + } + + /** + * Return the total bytes used by image files in the shared storage hosted + * on this volume. + * + * @return total bytes, or {@code -1} if no shared storage is hosted on this + * volume. + */ + public long getSharedImagesBytes() { + return sharedImagesBytes; + } + + /** {@hide} */ + public StorageSummary(String uuid) { + this.volumeUuid = uuid; + } + + /** {@hide} */ + public StorageSummary(Parcel in) { + this.volumeUuid = in.readString(); + this.totalBytes = in.readLong(); + this.freeBytes = in.readLong(); + this.sharedTotalBytes = in.readLong(); + this.sharedAudioBytes = in.readLong(); + this.sharedVideoBytes = in.readLong(); + this.sharedImagesBytes = in.readLong(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(volumeUuid); + dest.writeLong(totalBytes); + dest.writeLong(freeBytes); + dest.writeLong(sharedTotalBytes); + dest.writeLong(sharedAudioBytes); + dest.writeLong(sharedVideoBytes); + dest.writeLong(sharedImagesBytes); + } + + public static final Creator<StorageSummary> CREATOR = new Creator<StorageSummary>() { + @Override + public StorageSummary createFromParcel(Parcel in) { + return new StorageSummary(in); + } + + @Override + public StorageSummary[] newArray(int size) { + return new StorageSummary[size]; + } + }; +} diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 9dc60ab82f2d..ffe12482914d 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2680,6 +2680,7 @@ public abstract class Context { SEARCH_SERVICE, SENSOR_SERVICE, STORAGE_SERVICE, + STORAGE_STATS_SERVICE, WALLPAPER_SERVICE, VIBRATOR_SERVICE, //@hide: STATUS_BAR_SERVICE, @@ -3077,6 +3078,16 @@ public abstract class Context { public static final String STORAGE_SERVICE = "storage"; /** + * Use with {@link #getSystemService} to retrieve a {@link + * android.app.usage.StorageStatsManager} for accessing system storage + * statistics. + * + * @see #getSystemService + * @see android.app.usage.StorageStatsManager + */ + public static final String STORAGE_STATS_SERVICE = "storagestats"; + + /** * Use with {@link #getSystemService} to retrieve a * com.android.server.WallpaperService for accessing wallpapers. * diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 9b99bbfe8880..adc99d39d876 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -36,6 +36,8 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Objects; +import static android.os.Build.VERSION_CODES.DONUT; + /** * Information you can retrieve about a particular application. This * corresponds to information collected from the AndroidManifest.xml's @@ -1085,6 +1087,18 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS); } + /** + * Is using compatibility mode for non densty aware legacy applications. + * + * @hide + */ + public boolean usesCompatibilityMode() { + return targetSdkVersion < DONUT || + (flags & (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS | + FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS | + FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS)) == 0; + } + /** {@hide} */ public void initForUser(int userId) { uid = UserHandle.getUid(userId, UserHandle.getAppId(uid)); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index cf4c0fae6f16..ad1ed554a7a4 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -2387,10 +2387,28 @@ public class PackageParser { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES; } + // At this point we can check if an application is not supporting densities and hence + // cannot be windowed / resized. Note that an SDK version of 0 is common for + // pre-Doughnut applications. + if (pkg.applicationInfo.usesCompatibilityMode()) { + adjustPackageToBeUnresizeable(pkg); + } return pkg; } /** + * This is a pre-density application which will get scaled - instead of being pixel perfect. + * This type of application is not resizable. + * + * @param pkg The package which needs to be marked as unresizable. + */ + private void adjustPackageToBeUnresizeable(Package pkg) { + for (Activity a : pkg.activities) { + a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE; + } + } + + /** * Computes the targetSdkVersion to use at runtime. If the package is not * compatible with this platform, populates {@code outError[0]} with an * error message. diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index a4d891650c88..b4dcdf7e4e51 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -1061,11 +1061,6 @@ public final class ShortcutInfo implements Parcelable { * Launcher apps should show the launcher icon for the returned activity alongside * this shortcut. * - * <p>When a shortcut is dynamic or manifest - * (i.e. either {@link #isDynamic()} or {@link #isDeclaredInManifest()} returns {@code TRUE}), - * then it should always have a non-null target activity. - * Otherwise it will return null. - * * @see Builder#setActivity */ @Nullable @@ -1372,7 +1367,7 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return {@code TRUE} if a shortcut is pinned but neither manifest nor dynamic. + * @return true if pinned but neither static nor dynamic. * @hide */ public boolean isFloating() { diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 4e606ef4eede..717ac70ab430 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -16,18 +16,15 @@ package android.net; -import android.Manifest; import android.annotation.IntDef; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.content.Context; -import android.content.Intent; import android.net.NetworkScorerAppManager.NetworkScorerAppData; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; -import android.os.UserHandle; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -44,19 +41,11 @@ import java.lang.annotation.RetentionPolicy; * <p>A network scorer is any application which: * <ul> * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission. - * <li>Includes a receiver for {@link #ACTION_SCORE_NETWORKS} guarded by the - * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission which scores - * networks and (eventually) calls {@link #updateScores} with the results. If this receiver - * specifies an android:label attribute, this label will be used when referring to the - * application throughout system settings; otherwise, the application label will be used. + * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action + * protected by the {@link android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE} + * permission. * </ul> * - * <p>The system keeps track of an active scorer application; at any time, only this application - * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call - * {@link #updateScores}. Applications may determine the current active scorer with - * {@link #getActiveScorerPackage()} and request to change the active scorer by sending an - * {@link #ACTION_CHANGE_ACTIVE} broadcast with another scorer. - * * @hide */ @SystemApi @@ -263,12 +252,9 @@ public class NetworkScoreManager { /** * Request scoring for networks. * - * <p>Note that this is just a helper method to assemble the broadcast, and will run in the - * calling process. - * * @return true if the broadcast was sent, or false if there is no active scorer. * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission. + * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. * @hide */ public boolean requestScores(NetworkKey[] networks) throws SecurityException { @@ -285,7 +271,7 @@ public class NetworkScoreManager { * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission. + * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. * @throws IllegalArgumentException if a score cache is already registered for this type. * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE. * @hide @@ -302,7 +288,7 @@ public class NetworkScoreManager { * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores * @param filterType the {@link CacheUpdateFilter} to apply * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission. + * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. * @throws IllegalArgumentException if a score cache is already registered for this type. * @hide */ @@ -321,7 +307,7 @@ public class NetworkScoreManager { * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission. + * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. * @throws IllegalArgumentException if a score cache is already registered for this type. * @hide */ @@ -342,7 +328,8 @@ public class NetworkScoreManager { * request details * @return a {@link RecommendationResult} instance containing the recommended network * to connect to - * @throws SecurityException + * @throws SecurityException if the caller does not hold the + * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. */ public RecommendationResult requestRecommendation(RecommendationRequest request) throws SecurityException { diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java index b509d76d26e7..af328d0943ef 100644 --- a/core/java/android/os/BatteryProperties.java +++ b/core/java/android/os/BatteryProperties.java @@ -30,6 +30,7 @@ public class BatteryProperties implements Parcelable { public int batteryLevel; public int batteryVoltage; public int batteryTemperature; + public int batteryFullCharge; public int batteryChargeCounter; public String batteryTechnology; @@ -48,6 +49,7 @@ public class BatteryProperties implements Parcelable { batteryLevel = other.batteryLevel; batteryVoltage = other.batteryVoltage; batteryTemperature = other.batteryTemperature; + batteryFullCharge = other.batteryFullCharge; batteryChargeCounter = other.batteryChargeCounter; batteryTechnology = other.batteryTechnology; } @@ -69,6 +71,7 @@ public class BatteryProperties implements Parcelable { batteryLevel = p.readInt(); batteryVoltage = p.readInt(); batteryTemperature = p.readInt(); + batteryFullCharge = p.readInt(); batteryChargeCounter = p.readInt(); batteryTechnology = p.readString(); } @@ -85,6 +88,7 @@ public class BatteryProperties implements Parcelable { p.writeInt(batteryLevel); p.writeInt(batteryVoltage); p.writeInt(batteryTemperature); + p.writeInt(batteryFullCharge); p.writeInt(batteryChargeCounter); p.writeString(batteryTechnology); } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 8d73544602ba..013972d20e23 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -24,6 +24,7 @@ import java.util.Formatter; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -1342,9 +1343,11 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_WAKEUP_AP = 0x0013; // Event for reporting that a specific partial wake lock has been held for a long duration. public static final int EVENT_LONG_WAKE_LOCK = 0x0014; + // Event reporting the new estimated (learned) capacity of the battery in mAh. + public static final int EVENT_ESTIMATED_BATTERY_CAP = 0x0015; // Number of event types. - public static final int EVENT_COUNT = 0x0015; + public static final int EVENT_COUNT = 0x0016; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -2040,13 +2043,28 @@ public abstract class BatteryStats implements Parcelable { public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist", - "screenwake", "wakeupap", "longwake" + "screenwake", "wakeupap", "longwake", "est_capacity" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw", - "Esw", "Ewa", "Elw" + "Esw", "Ewa", "Elw", "Eec" + }; + + @FunctionalInterface + public interface IntToString { + String applyAsString(int val); + } + + private static final IntToString sUidToString = UserHandle::formatUid; + private static final IntToString sIntToString = Integer::toString; + + public static final IntToString[] HISTORY_EVENT_INT_FORMATTERS = new IntToString[] { + sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, + sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, + sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, + sUidToString, sUidToString, sUidToString, sIntToString }; /** @@ -4975,7 +4993,8 @@ public abstract class BatteryStats implements Parcelable { if (checkin) { pw.print(rec.eventTag.poolIdx); } else { - UserHandle.formatUid(pw, rec.eventTag.uid); + pw.append(HISTORY_EVENT_INT_FORMATTERS[idx] + .applyAsString(rec.eventTag.uid)); pw.print(":\""); pw.print(rec.eventTag.string); pw.print("\""); diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 3fc7dba042da..03fd8d3af061 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -52,6 +52,7 @@ import com.android.internal.util.Preconditions; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.lang.ref.WeakReference; @@ -974,10 +975,17 @@ public class StorageManager { try (final FileInputStream fis = new FileInputStream(path); final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) { return Long.parseLong(reader.readLine()); + } catch (FileNotFoundException e) { + // This is expected since we are trying to parse multiple paths. + Slog.i(TAG, "readLong(): Path doesn't exist: " + path + ": " + e); + return 0; + } catch (NumberFormatException e) { + Slog.e(TAG, "readLong(): Could not parse " + path + ": " + e); + return 0; } catch (Exception e) { - Slog.w(TAG, "readLong(): could not read " + path + ": " + e); + Slog.e(TAG, "readLong(): Unknown exception while opening " + path + ": " + e); return 0; - } + } } /** @removed */ diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index 7747580892f1..95150409514d 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -200,8 +200,7 @@ public class RenderNodeAnimator extends Animator { // in mTransformationInfo instead of in RenderNode, so we need to update // it with the final value here. if (mRenderProperty == RenderNodeAnimator.ALPHA) { - // Don't need null check because ViewPropertyAnimator's - // ctor calls ensureTransformationInfo() + mViewTarget.ensureTransformationInfo(); mViewTarget.mTransformationInfo.mAlpha = mFinalValue; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index aa941b8fcfb4..aad7e0a12398 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3394,7 +3394,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, float mTransitionAlpha = 1f; } - TransformationInfo mTransformationInfo; + /** @hide */ + public TransformationInfo mTransformationInfo; /** * Current clip bounds. to which all drawing of this view are constrained. diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index dd63fef5f26f..3213a34e28f1 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -169,7 +169,7 @@ public abstract class CompoundButton extends Button implements Checkable { * * @param listener the callback to call on checked state change */ - public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { + public void setOnCheckedChangeListener(@Nullable OnCheckedChangeListener listener) { mOnCheckedChangeListener = listener; } diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 5623a2cb430c..99a25fd8526b 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -125,7 +125,7 @@ interface IBatteryStats { void noteNetworkStatsEnabled(); void noteDeviceIdleMode(int mode, String activeReason, int activeUid); void setBatteryState(int status, int health, int plugType, int level, int temp, int volt, - int chargeUAh); + int chargeUAh, int chargeFullUAh); long getAwakeTimeBattery(); long getAwakeTimePlugged(); diff --git a/core/java/com/android/internal/logging/EventLogTags.logtags b/core/java/com/android/internal/logging/EventLogTags.logtags index 4364cc39af3f..93d5a0373d2d 100644 --- a/core/java/com/android/internal/logging/EventLogTags.logtags +++ b/core/java/com/android/internal/logging/EventLogTags.logtags @@ -5,5 +5,6 @@ option java_package com.android.internal.logging; # interaction logs 524287 sysui_view_visibility (category|1|5),(visible|1|6) 524288 sysui_action (category|1|5),(pkg|3) +524292 sysui_multi_action (content|4) 524290 sysui_count (name|3),(increment|1) 524291 sysui_histogram (name|3),(bucket|1) diff --git a/core/java/com/android/internal/logging/LogBuilder.java b/core/java/com/android/internal/logging/LogBuilder.java new file mode 100644 index 000000000000..634d061e79d1 --- /dev/null +++ b/core/java/com/android/internal/logging/LogBuilder.java @@ -0,0 +1,67 @@ +package com.android.internal.logging; + +import android.util.EventLog; +import android.util.SparseArray; +import android.view.View; + +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; + + +/** + * Helper class to assemble more complex logs. + * + * @hide + */ + +public class LogBuilder { + + private SparseArray<Object> entries = new SparseArray(); + + public LogBuilder() {} + + + public LogBuilder setView(View view) { + entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_VIEW, view.getId()); + return this; + } + + public LogBuilder setCategory(int category) { + entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY, category); + return this; + } + + public LogBuilder setType(int type) { + entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_TYPE, type); + return this; + } + + /** + * @param tag From your MetricsEvent enum. + * @param value One of Integer, Long, Float, String + * @return + */ + public LogBuilder addTaggedData(int tag, Object value) { + if (!(value instanceof Integer || + value instanceof String || + value instanceof Long || + value instanceof Float)) { + throw new IllegalArgumentException( + "Value must be loggable type - int, long, float, String"); + } + entries.put(tag, value); + return this; + } + + /** + * Assemble logs into structure suitable for EventLog. + */ + public Object[] serialize() { + Object[] out = new Object[entries.size() * 2]; + for (int i = 0; i < entries.size(); i++) { + out[i * 2] = entries.keyAt(i); + out[i * 2 + 1] = entries.valueAt(i); + } + return out; + } +} + diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java index a94f30867e40..5eb39aed2c7b 100644 --- a/core/java/com/android/internal/logging/MetricsLogger.java +++ b/core/java/com/android/internal/logging/MetricsLogger.java @@ -17,10 +17,12 @@ package com.android.internal.logging; import android.content.Context; import android.os.Build; +import android.util.EventLog; import android.view.View; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; + /** * Log all the things. * @@ -71,6 +73,14 @@ public class MetricsLogger { action(context, category, Boolean.toString(value)); } + public static void action(LogBuilder content) { + //EventLog.writeEvent(524292, content.serialize()); + // Below would be the *right* way to do this, using the generated + // EventLogTags method, but that doesn't work. + EventLogTags.writeSysuiMultiAction(content.serialize()); + } + + public static void action(Context context, int category, String pkg) { if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) { throw new IllegalArgumentException("Must define metric category"); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 5d49d12554e3..5fd68e6ff1e6 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -559,6 +559,10 @@ public class BatteryStatsImpl extends BatteryStats { private int mEstimatedBatteryCapacity = -1; + // Last learned capacity reported by BatteryService in + // setBatteryState(). + private int mLastChargeFullUAh = 0; + private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry(); private PowerProfile mPowerProfile; @@ -9818,7 +9822,7 @@ public class BatteryStatsImpl extends BatteryStats { public static final int BATTERY_PLUGGED_NONE = 0; public void setBatteryStateLocked(int status, int health, int plugType, int level, - int temp, int volt, int chargeUAh) { + int temp, int volt, int chargeUAh, int chargeFullUAh) { final boolean onBattery = plugType == BATTERY_PLUGGED_NONE; final long uptime = mClocks.uptimeMillis(); final long elapsedRealtime = mClocks.elapsedRealtime(); @@ -9980,6 +9984,16 @@ public class BatteryStatsImpl extends BatteryStats { // The next time we are unplugged, history will be cleared. mRecordingHistory = DEBUG; } + + if (differsByMoreThan(chargeFullUAh, mLastChargeFullUAh, 100)) { + mLastChargeFullUAh = chargeFullUAh; + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ESTIMATED_BATTERY_CAP, + "", chargeFullUAh / 1000); + } + } + + private static boolean differsByMoreThan(int left, int right, int diff) { + return Math.abs(left - right) > diff; } public long getAwakeTimeBattery() { diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp index be9449b6eb5c..9ce5670f904c 100644 --- a/core/jni/android_graphics_Canvas.cpp +++ b/core/jni/android_graphics_Canvas.cpp @@ -219,13 +219,6 @@ static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHan return nonEmptyClip ? JNI_TRUE : JNI_FALSE; } -static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle, - jint opHandle) { - SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle); - bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, opHandleToClipOp(opHandle)); - return nonEmptyClip ? JNI_TRUE : JNI_FALSE; -} - static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) { SkBlendMode mode = static_cast<SkBlendMode>(modeHandle); get_canvas(canvasHandle)->drawColor(color, mode); @@ -616,7 +609,6 @@ static const JNINativeMethod gMethods[] = { {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect}, {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath}, - {"nClipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion}, {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter}, }; diff --git a/core/jni/android_hardware_Radio.cpp b/core/jni/android_hardware_Radio.cpp index 42ceec416590..397e67bab488 100644 --- a/core/jni/android_hardware_Radio.cpp +++ b/core/jni/android_hardware_Radio.cpp @@ -313,12 +313,14 @@ static jint convertProgramInfoFromNative(JNIEnv *env, ALOGV("%s", __FUNCTION__); int jStatus; jobject jMetadata = NULL; - if (nProgramInfo->metadata != NULL) { - ALOGV("%s metadata %p", __FUNCTION__, nProgramInfo->metadata); - jStatus = convertMetadataFromNative(env, &jMetadata, nProgramInfo->metadata); - if (jStatus < 0) { - return jStatus; - } + + if (nProgramInfo == nullptr || nProgramInfo->metadata == nullptr) { + return (jint)RADIO_STATUS_BAD_VALUE; + } + + jStatus = convertMetadataFromNative(env, &jMetadata, nProgramInfo->metadata); + if (jStatus < 0) { + return jStatus; } ALOGV("%s channel %d tuned %d", __FUNCTION__, nProgramInfo->channel, nProgramInfo->tuned); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4b4fd846df08..48805d8a6544 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -480,6 +480,9 @@ <protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" /> <protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" /> + <protected-broadcast android:name="android.accounts.action.VISIBLE_ACCOUNTS_CHANGED" /> + <protected-broadcast android:name="android.accounts.action.ACCOUNTS_LISTENER_PACKAGE_INSTALLED" /> + <protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" /> <protected-broadcast android:name="com.android.phone.SIP_INCOMING_CALL" /> @@ -1259,7 +1262,7 @@ recommendations and scores from the NetworkScoreService. <p>Not for use by third-party applications. @hide --> <permission android:name="android.permission.REQUEST_NETWORK_SCORES" - android:protectionLevel="signature|privileged" /> + android:protectionLevel="signature" /> <!-- ======================================= --> <!-- Permissions for short range, peripheral networks --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5967c692fb94..9cbb8c3b0167 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1260,9 +1260,8 @@ <!-- A list of potential packages, in priority order, that may contain a network recommendation provider. A network recommendation provider must: * Be granted the SCORE_NETWORKS permission. - * Include a Receiver for the android.net.scoring.SCORE_NETWORKS action guarded by the - BROADCAST_NETWORK_PRIVILEGED permission. - * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action. + * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action + protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission. This may be empty if network scoring and recommending isn't supported. --> @@ -2697,4 +2696,7 @@ <!-- Flag indicates that whether non-system apps can be installed on internal storage. --> <bool name="config_allow3rdPartyAppOnInternal">true</bool> + + <!-- Component name of the default cell broadcast receiver --> + <string name="config_defaultCellBroadcastReceiverComponent" translatable="false">com.android.cellbroadcastreceiver/.PrivilegedCellBroadcastReceiver</string> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 880944e659e6..b7f5a9bb3a13 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4135,7 +4135,7 @@ <string name="date_picker_day_typeface">sans-serif-medium</string> <!-- Notify use that they are in Lock-to-app --> - <string name="lock_to_app_toast">To unpin this screen, touch & hold Back.</string> + <string name="lock_to_app_toast">To unpin this screen, touch & hold Back and Overview.</string> <!-- Notify user that they are locked in lock-to-app mode --> <string name="lock_to_app_toast_locked">App is pinned: Unpinning isn\'t allowed on this device.</string> <!-- Starting lock-to-app indication. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 18228b5a95c3..c9ea21a6ce41 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2778,4 +2778,6 @@ <java-symbol type="bool" name="use_lock_pattern_drawable" /> <java-symbol type="drawable" name="lockscreen_notselected" /> <java-symbol type="drawable" name="lockscreen_selected" /> + + <java-symbol type="string" name="config_defaultCellBroadcastReceiverComponent" /> </resources> diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index cd419878bb50..e3a85b562068 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -1107,6 +1107,13 @@ </intent-filter> </activity> + <activity android:name="android.app.Activity" android:label="Empty Activity"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" /> + </intent-filter> + </activity> + <!-- Activity-level metadata --> <meta-data android:name="com.android.frameworks.coretests.isApp" android:value="true" /> <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" /> diff --git a/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java b/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java new file mode 100644 index 000000000000..b52d98c906c4 --- /dev/null +++ b/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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.view; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import android.app.Activity; +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.annotation.UiThreadTest; +import android.support.test.filters.MediumTest; +import android.support.test.rule.ActivityTestRule; + +import org.junit.Rule; +import org.junit.Test; + +@MediumTest +public class RenderNodeAnimatorTest { + @Rule + public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class); + + private Context getContext() { + return InstrumentationRegistry.getTargetContext(); + } + + private Activity getActivity() { + return mActivityRule.getActivity(); + } + + @UiThreadTest + @Test + public void testAlphaTransformationInfo() throws Throwable { + View view = new View(getContext()); + + // attach the view, since otherwise the RenderNodeAnimator won't accept view as target + getActivity().setContentView(view); + + RenderNodeAnimator anim = new RenderNodeAnimator(RenderNodeAnimator.ALPHA, 0.5f); + anim.setTarget(view); + assertNull(view.mTransformationInfo); + anim.start(); // should initialize mTransformationInfo + assertNotNull(view.mTransformationInfo); + } +} diff --git a/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java b/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java new file mode 100644 index 000000000000..e7d23a8edb9c --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java @@ -0,0 +1,43 @@ +package com.android.internal.logging; + +import junit.framework.TestCase; + +public class LogBuilderTest extends TestCase { + + public void testSerialize() { + LogBuilder builder = new LogBuilder(); + builder.addTaggedData(1, "one"); + builder.addTaggedData(2, "two"); + Object[] out = builder.serialize(); + assertEquals(1, out[0]); + assertEquals("one", out[1]); + assertEquals(2, out[2]); + assertEquals("two", out[3]); + } + + public void testInvalidInputThrows() { + LogBuilder builder = new LogBuilder(); + boolean threw = false; + try { + builder.addTaggedData(0, new Object()); + } catch (IllegalArgumentException e) { + threw = true; + } + assertTrue(threw); + assertEquals(0, builder.serialize().length); + } + + public void testValidInputTypes() { + LogBuilder builder = new LogBuilder(); + builder.addTaggedData(1, "onetwothree"); + builder.addTaggedData(2, 123); + builder.addTaggedData(3, 123L); + builder.addTaggedData(4, 123.0F); + Object[] out = builder.serialize(); + assertEquals("onetwothree", out[1]); + assertEquals(123, out[3]); + assertEquals(123L, out[5]); + assertEquals(123.0F, out[7]); + } + +} diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index b0934586b27c..cc5cc7bd8cf8 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -801,12 +801,13 @@ public class Canvas extends BaseCanvas { * @param op How the clip is modified * @return true if the resulting is non-empty * + * @removed * @deprecated Unlike all other clip calls this API does not respect the * current matrix. Use {@link #clipRect(Rect)} as an alternative. */ @Deprecated public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) { - return nClipRegion(mNativeCanvasWrapper, region.ni(), op.nativeInt); + return false; } /** @@ -819,12 +820,13 @@ public class Canvas extends BaseCanvas { * @param region The region to operate on the current clip, based on op * @return true if the resulting is non-empty * + * @removed * @deprecated Unlike all other clip calls this API does not respect the * current matrix. Use {@link #clipRect(Rect)} as an alternative. */ @Deprecated public boolean clipRegion(@NonNull Region region) { - return clipRegion(region, Region.Op.INTERSECT); + return false; } public @Nullable DrawFilter getDrawFilter() { @@ -1115,10 +1117,6 @@ public class Canvas extends BaseCanvas { long nativePath, int regionOp); @FastNative - private static native boolean nClipRegion(long nativeCanvas, - long nativeRegion, - int regionOp); - @FastNative private static native void nSetDrawFilter(long nativeCanvas, long nativeFilter); @FastNative diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp index f5aef05e8842..d433b90f14f0 100644 --- a/libs/androidfw/AttributeResolution.cpp +++ b/libs/androidfw/AttributeResolution.cpp @@ -418,8 +418,10 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags; out_values[STYLE_DENSITY] = config.density; - if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) { + if (value.dataType != Res_value::TYPE_NULL) { indices_idx++; + + // out_indices must NOT be nullptr. out_indices[indices_idx] = ii; } @@ -428,9 +430,8 @@ void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_s res.unlock(); - if (out_indices != nullptr) { - out_indices[0] = indices_idx; - } + // out_indices must NOT be nullptr. + out_indices[0] = indices_idx; } bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h index 8d5ff461444e..69b760414846 100644 --- a/libs/androidfw/include/androidfw/AttributeResolution.h +++ b/libs/androidfw/include/androidfw/AttributeResolution.h @@ -40,14 +40,20 @@ enum { // TODO(adamlesinski): Run performance tests against these methods and a new, single method // that uses all the sources and branches to the right ones within the inner loop. +// `out_values` must NOT be nullptr. +// `out_indices` may be nullptr. bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, uint32_t def_style_res, uint32_t* src_values, size_t src_values_length, uint32_t* attrs, size_t attrs_length, uint32_t* out_values, uint32_t* out_indices); +// `out_values` must NOT be nullptr. +// `out_indices` is NOT optional and must NOT be nullptr. void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr, uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length, uint32_t* out_values, uint32_t* out_indices); +// `out_values` must NOT be nullptr. +// `out_indices` may be nullptr. bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs, size_t attrs_length, uint32_t* out_values, uint32_t* out_indices); diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp index d417aba1c595..75505171133c 100644 --- a/libs/androidfw/tests/AttributeResolution_test.cpp +++ b/libs/androidfw/tests/AttributeResolution_test.cpp @@ -16,6 +16,8 @@ #include "androidfw/AttributeResolution.h" +#include <array> + #include "android-base/file.h" #include "android-base/logging.h" #include "android-base/macros.h" @@ -67,15 +69,13 @@ TEST_F(AttributeResolutionTest, Theme) { ResTable::Theme theme(table_); ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo)); - uint32_t attrs[] = {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, - R::attr::attr_four}; - std::vector<uint32_t> values; - values.resize(arraysize(attrs) * 6); + std::array<uint32_t, 4> attrs{ + {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}}; + std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values; ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/, - nullptr /*src_values*/, 0 /*src_values_length*/, - attrs, arraysize(attrs), values.data(), - nullptr /*out_indices*/)); + nullptr /*src_values*/, 0 /*src_values_length*/, attrs.data(), + attrs.size(), values.data(), nullptr /*out_indices*/)); const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC; @@ -112,13 +112,12 @@ TEST_F(AttributeResolutionTest, Theme) { } TEST_F(AttributeResolutionXmlTest, XmlParser) { - uint32_t attrs[] = {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, - R::attr::attr_four}; - std::vector<uint32_t> values; - values.resize(arraysize(attrs) * 6); + std::array<uint32_t, 4> attrs{ + {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}}; + std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values; - ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs, arraysize(attrs), - values.data(), nullptr /*out_indices*/)); + ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(), + nullptr /*out_indices*/)); uint32_t* values_cursor = values.data(); EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]); @@ -157,14 +156,13 @@ TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) { ResTable::Theme theme(table_); ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo)); - uint32_t attrs[] = {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, - R::attr::attr_four, R::attr::attr_five}; - std::vector<uint32_t> values; - values.resize(arraysize(attrs) * 6); + std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, + R::attr::attr_four, R::attr::attr_five}}; + std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values; + std::array<uint32_t, attrs.size()> indices; - ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, - 0 /*def_style_res*/, attrs, arraysize(attrs), - values.data(), nullptr /*out_indices*/); + ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(), + attrs.size(), values.data(), indices.data()); const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC; diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp index dbbf00d8bdec..9c068b080d45 100644 --- a/libs/hwui/CanvasState.cpp +++ b/libs/hwui/CanvasState.cpp @@ -212,11 +212,6 @@ bool CanvasState::clipPath(const SkPath* path, SkClipOp op) { return !mSnapshot->clipIsEmpty(); } -bool CanvasState::clipRegion(const SkRegion* region, SkClipOp op) { - mSnapshot->clipRegionTransformed(*region, op); - return !mSnapshot->clipIsEmpty(); -} - void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) { Rect bounds; float radius; diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h index a805597ac9b9..b1fe09eb1aec 100644 --- a/libs/hwui/CanvasState.h +++ b/libs/hwui/CanvasState.h @@ -124,7 +124,6 @@ public: bool clipRect(float left, float top, float right, float bottom, SkClipOp op); bool clipPath(const SkPath* path, SkClipOp op); - bool clipRegion(const SkRegion* region, SkClipOp op); /** * Sets a "clipping outline", which is independent from the regular clip. diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h index 2e561601d452..cf5751606d12 100644 --- a/libs/hwui/ClipArea.h +++ b/libs/hwui/ClipArea.h @@ -146,7 +146,6 @@ public: void setClip(float left, float top, float right, float bottom); void clipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op); - void clipRegion(const SkRegion& region, SkRegion::Op op); void clipPathWithTransform(const SkPath& path, const mat4* transform, SkRegion::Op op); @@ -195,6 +194,7 @@ private: void regionModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op); + void clipRegion(const SkRegion& region, SkRegion::Op op); void ensureClipRegion(); void onClipRegionUpdated(); diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index effc65ea967f..4f9a3de64fc2 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -22,6 +22,7 @@ #include "Caches.h" #include "Debug.h" #include "Extensions.h" +#include "font/Font.h" #include "Glop.h" #include "GlopBuilder.h" #include "PixelBuffer.h" diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 96c6d29af221..ee6279dccb92 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -240,9 +240,6 @@ bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, bool RecordingCanvas::clipPath(const SkPath* path, SkClipOp op) { return mState.clipPath(path, op); } -bool RecordingCanvas::clipRegion(const SkRegion* region, SkClipOp op) { - return mState.clipRegion(region, op); -} // ---------------------------------------------------------------------------- // android/graphics/Canvas draw operations diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 5d4938581d20..44181bd22397 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -134,7 +134,6 @@ public: virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override; virtual bool clipPath(const SkPath* path, SkClipOp op) override; - virtual bool clipRegion(const SkRegion* region, SkClipOp op) override; // Misc virtual SkDrawFilter* getDrawFilter() override { return mDrawFilter.get(); } diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 8cae771f39b2..344df0a70da5 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -416,23 +416,6 @@ bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) { return !mCanvas->isClipEmpty(); } -bool SkiaCanvas::clipRegion(const SkRegion* region, SkClipOp op) { - SkPath rgnPath; - if (region->getBoundaryPath(&rgnPath)) { - // The region is specified in device space. - SkMatrix savedMatrix = mCanvas->getTotalMatrix(); - mCanvas->resetMatrix(); - this->recordClip(rgnPath, op); - mCanvas->clipPath(rgnPath, op); - mCanvas->setMatrix(savedMatrix); - } else { - const auto emptyClip = SkRect::MakeEmpty(); - this->recordClip(emptyClip, op); - mCanvas->clipRect(emptyClip, op); - } - return !mCanvas->isClipEmpty(); -} - // ---------------------------------------------------------------------------- // Canvas state operations: Filters // ---------------------------------------------------------------------------- diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 9639ebd19bbb..34c3717557ff 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -94,7 +94,6 @@ public: virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override; virtual bool clipPath(const SkPath* path, SkClipOp op) override; - virtual bool clipRegion(const SkRegion* region, SkClipOp op) override; virtual SkDrawFilter* getDrawFilter() override; virtual void setDrawFilter(SkDrawFilter* drawFilter) override; diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp index 2a7f5756a007..c5156cfd6844 100644 --- a/libs/hwui/SkiaCanvasProxy.cpp +++ b/libs/hwui/SkiaCanvasProxy.cpp @@ -478,9 +478,5 @@ void SkiaCanvasProxy::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle) mCanvas->clipPath(&path, op); } -void SkiaCanvasProxy::onClipRegion(const SkRegion& region, SkClipOp op) { - mCanvas->clipRegion(®ion, op); -} - }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h index 40ddc34c79ba..b3f6c07dfe64 100644 --- a/libs/hwui/SkiaCanvasProxy.h +++ b/libs/hwui/SkiaCanvasProxy.h @@ -100,7 +100,6 @@ protected: virtual void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override; virtual void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override; virtual void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override; - virtual void onClipRegion(const SkRegion&, SkClipOp) override; private: Canvas* mCanvas; diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp index 3f08009b6be9..9d719bd1e997 100644 --- a/libs/hwui/Snapshot.cpp +++ b/libs/hwui/Snapshot.cpp @@ -72,11 +72,6 @@ Snapshot::Snapshot(Snapshot* s, int saveFlags) // Clipping /////////////////////////////////////////////////////////////////////////////// -void Snapshot::clipRegionTransformed(const SkRegion& region, SkClipOp op) { - flags |= Snapshot::kFlagClipSet; - mClipArea->clipRegion(region, static_cast<SkRegion::Op>(op)); -} - void Snapshot::clip(const Rect& localClip, SkClipOp op) { flags |= Snapshot::kFlagClipSet; mClipArea->clipRectWithTransform(localClip, transform, static_cast<SkRegion::Op>(op)); diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index 4f92657d01ba..8cd90a68a9bb 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -118,12 +118,6 @@ public: void clipTransformed(const Rect& r, SkClipOp op = SkClipOp::kIntersect); /** - * Modifies the current clip with the specified region and operation. - * The specified region is considered already transformed. - */ - void clipRegionTransformed(const SkRegion& region, SkClipOp op); - - /** * Modifies the current clip with the specified path and operation. */ void clipPath(const SkPath& path, SkClipOp op); diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index e7b6b2d329f1..969d87716ce6 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -184,7 +184,6 @@ public: virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) = 0; virtual bool clipPath(const SkPath* path, SkClipOp op) = 0; - virtual bool clipRegion(const SkRegion* region, SkClipOp op) = 0; // filters virtual SkDrawFilter* getDrawFilter() = 0; diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index 362cf4468913..5c00985474f4 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -100,6 +100,129 @@ <item>Always use HDCP checking</item> </string-array> + + <!-- Bluetooth settings --> + + <!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item>Default</item> + <item>SBC</item> + <item>aptX</item> + <item>aptX-HD</item> + <item>LDAC</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec selection preference. --> + <string-array name="bluetooth_a2dp_codec_values" translatable="false" > + <item>1000000</item> + <item>0</item> + <item>1</item> + <item>2</item> + <item>3</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_summaries" > + <item>Default</item> + <item>SBC</item> + <item>aptX</item> + <item>aptX-HD</item> + <item>LDAC</item> + </string-array> + + <!-- Titles for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> + <item>Default</item> + <item>44.1 kHz</item> + <item>48.0 kHz</item> + <item>88.2 kHz</item> + <item>96.0 kHz</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec Sample Rate selection preference. --> + <string-array name="bluetooth_a2dp_codec_sample_rate_values" translatable="false" > + <item>0</item> + <item>1</item> + <item>2</item> + <item>4</item> + <item>8</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_sample_rate_summaries" > + <item>Default</item> + <item>44.1 kHz</item> + <item>48.0 kHz</item> + <item>88.2 kHz</item> + <item>96.0 kHz</item> + </string-array> + + <!-- Titles for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles"> + <item>Default</item> + <item>16 bits/sample</item> + <item>24 bits/sample</item> + <item>32 bits/sample</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec Bits Per Sample selection preference. --> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_values" translatable="false" > + <item>0</item> + <item>1</item> + <item>2</item> + <item>4</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries" > + <item>Default</item> + <item>16 bits/sample</item> + <item>24 bits/sample</item> + <item>32 bits/sample</item> + </string-array> + + <!-- Titles for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_channel_mode_titles"> + <item>Default</item> + <item>Mono</item> + <item>Stereo</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec Channel Mode selection preference. --> + <string-array name="bluetooth_a2dp_codec_channel_mode_values" translatable="false" > + <item>0</item> + <item>1</item> + <item>2</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_channel_mode_summaries" > + <item>Default</item> + <item>Mono</item> + <item>Stereo</item> + </string-array> + + <!-- Titles for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item>Sound quality preferred (990kbps/909kbps)</item> + <item>Standard (660kbps/606kbps)</item> + <item>Connection preferred (330kbps/303kbps)</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec LDAC Playback Quaility selection preference. --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_values" translatable="false" > + <item>1000</item> + <item>1001</item> + <item>1002</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries" > + <item>Sound quality preferred (990kbps/909kbps)</item> + <item>Standard (660kbps/606kbps)</item> + <item>Connection preferred (330kbps/303kbps)</item> + </string-array> + <!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] --> <string-array name="select_logd_size_titles"> <item>Off</item> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index f176aac09856..93bd5dc489d0 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -428,6 +428,31 @@ <!-- Setting Checkbox title for disabling Bluetooth absolute volume --> <string name="bluetooth_disable_absolute_volume">Disable absolute volume</string> + <!-- UI debug setting: Select Bluetooth Audio Codec --> + <string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec --> + <string name="bluetooth_select_a2dp_codec_type_dialog_title">Select Preferred Bluetooth A2DP Codec</string> + + <!-- UI debug setting: Select Bluetooth Audio Sample Rate --> + <string name="bluetooth_select_a2dp_codec_sample_rate">Bluetooth Audio Sample Rate</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Sample Rate --> + <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title">Select Preferred Bluetooth A2DP Codec Sample Rate</string> + + <!-- UI debug setting: Select Bluetooth Audio Bits Per Sample --> + <string name="bluetooth_select_a2dp_codec_bits_per_sample">Bluetooth Audio Bits Per Sample</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Bits Per Sample --> + <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title">Select Preferred Bluetooth A2DP Codec Bits Per Sample</string> + + <!-- UI debug setting: Select Bluetooth Audio Channel Mode --> + <string name="bluetooth_select_a2dp_codec_channel_mode">Bluetooth Audio Channel Mode</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Channel Mode --> + <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title">Select Preferred Bluetooth A2DP Codec Channel Mode</string> + + <!-- UI debug setting: Select Bluetooth Audio LDAC Playback Quality --> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality">Bluetooth Audio LDAC Playback Quality</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec LDAC Playback Quality --> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Select Preferred Bluetooth A2DP Codec LDAC Playback Quality</string> + <!-- setting Checkbox summary whether to show options for wireless display certification --> <string name="wifi_display_certification_summary">Show options for wireless display certification</string> <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] --> diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java index 587744065d77..5c7496d437f4 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java @@ -38,6 +38,7 @@ import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsDebugFlags; import com.android.systemui.recents.misc.SystemServicesProxy; +import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -150,11 +151,19 @@ public class RecentsTaskLoadPlan { Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent, t.userId, t.firstActiveTime, t.lastActiveTime); - // This task is only shown in the stack if it statisfies the historical time or min + // This task is only shown in the stack if it satisfies the historical time or min // number of tasks constraints. Freeform tasks are also always shown. boolean isFreeformTask = SystemServicesProxy.isFreeformStack(t.stackId); - boolean isStackTask = isFreeformTask || !isHistoricalTask(t) || + boolean isStackTask; + if (Recents.getConfiguration().isGridEnabled) { + // When grid layout is enabled, we only show the first + // TaskGridLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT} tasks. + isStackTask = t.lastActiveTime >= lastStackActiveTime && + i >= taskCount - TaskGridLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT; + } else { + isStackTask = isFreeformTask || !isHistoricalTask(t) || (t.lastActiveTime >= lastStackActiveTime && i >= (taskCount - MIN_NUM_TASKS)); + } boolean isLaunchTarget = taskKey.id == runningTaskId; // The last stack active time is the baseline for which we show visible tasks. Since diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java index be3af040c748..046ced4aa57f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java @@ -30,7 +30,7 @@ import com.android.systemui.recents.views.TaskViewTransform; public class TaskGridLayoutAlgorithm { private final String TAG = "TaskGridLayoutAlgorithm"; - private final int MAX_LAYOUT_TASK_COUNT = 8; + public static final int MAX_LAYOUT_TASK_COUNT = 8; /** The horizontal padding around the whole recents view. */ private int mPaddingLeftRight; @@ -135,6 +135,16 @@ public class TaskGridLayoutAlgorithm { updateAppAspectRatio(); } + /** + * Returns the proper task view transform of a certain task view, according to its index and the + * amount of task views. + * @param taskIndex The index of the task view whose transform we want. It's never greater + * than {@link MAX_LAYOUT_TASK_COUNT}. + * @param taskCount The current amount of task views. + * @param transformOut The result transform that this method returns. + * @param stackLayout The base stack layout algorithm. + * @return The expected transform of the (taskIndex)th task view. + */ public TaskViewTransform getTransform(int taskIndex, int taskCount, TaskViewTransform transformOut, TaskStackLayoutAlgorithm stackLayout) { diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index eed7e70866d3..2048cc8e5b02 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3165,6 +3165,13 @@ message MetricsEvent { // CATEGORY: Settings DIALOG_SUPPORT_SYSTEM_INFORMATION = 756; + // These values should never appear in log outputs - they are reserved for + // internal Tron use. + RESERVED_FOR_LOGBUILDER_VIEW = 757; + RESERVED_FOR_LOGBUILDER_CATEGORY = 758; + RESERVED_FOR_LOGBUILDER_TYPE = 759; + + // ---- End O Constants, all O constants go above this line ---- // Add new aosp constants above this line. diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 573ad631891e..dd550f22f992 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -347,13 +347,14 @@ public final class BatteryService extends SystemService { + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline + ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent + ", maxChargingVoltage" + mBatteryProps.maxChargingVoltage - + ", chargeCounter" + mBatteryProps.batteryChargeCounter + ", batteryStatus=" + mBatteryProps.batteryStatus + ", batteryHealth=" + mBatteryProps.batteryHealth + ", batteryPresent=" + mBatteryProps.batteryPresent + ", batteryLevel=" + mBatteryProps.batteryLevel + ", batteryTechnology=" + mBatteryProps.batteryTechnology + ", batteryVoltage=" + mBatteryProps.batteryVoltage + + ", batteryChargeCounter=" + mBatteryProps.batteryChargeCounter + + ", batteryFullCharge=" + mBatteryProps.batteryFullCharge + ", batteryTemperature=" + mBatteryProps.batteryTemperature + ", mBatteryLevelCritical=" + mBatteryLevelCritical + ", mPlugType=" + mPlugType); @@ -363,7 +364,8 @@ public final class BatteryService extends SystemService { try { mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature, - mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter); + mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter, + mBatteryProps.batteryFullCharge); } catch (RemoteException e) { // Should never happen. } diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index 983d0392f0bc..cef459a3ae39 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -34,9 +34,9 @@ import android.net.INetworkRecommendationProvider; import android.net.INetworkScoreCache; import android.net.INetworkScoreService; import android.net.NetworkKey; +import android.net.NetworkScoreManager; import android.net.NetworkScorerAppManager; import android.net.NetworkScorerAppManager.NetworkScorerAppData; -import android.net.NetworkScoreManager; import android.net.RecommendationRequest; import android.net.RecommendationResult; import android.net.ScoredNetwork; @@ -380,13 +380,16 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } + private boolean isCallerSystemUid() { + // REQUEST_NETWORK_SCORES is a signature only permission. + return mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES) == + PackageManager.PERMISSION_GRANTED; + } + @Override public boolean clearScores() { - // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED) - // should be allowed to flush all scores. - if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) || - mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) == - PackageManager.PERMISSION_GRANTED) { + // Only the active scorer or the system should be allowed to flush all scores. + if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) { final long token = Binder.clearCallingIdentity(); try { clearInternal(); @@ -409,7 +412,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { // In the future, should this API be opened to 3p apps, we will need to lock this down and // figure out another way to streamline the UX. - // mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG); // Scorers (recommendation providers) are selected and no longer set. @@ -418,11 +420,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public void disableScoring() { - // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED) - // should be allowed to disable scoring. - if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) || - mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) == - PackageManager.PERMISSION_GRANTED) { + // Only the active scorer or the system should be allowed to disable scoring. + if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) { // no-op for now but we could write to the setting if needed. } else { throw new SecurityException( @@ -450,7 +449,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache, int filterType) { - mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); + mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); final long token = Binder.clearCallingIdentity(); try { synchronized (mScoreCaches) { @@ -475,7 +474,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { - mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); + mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); final long token = Binder.clearCallingIdentity(); try { synchronized (mScoreCaches) { @@ -496,7 +495,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public RecommendationResult requestRecommendation(RecommendationRequest request) { - mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); + mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); throwIfCalledOnMainThread(); final long token = Binder.clearCallingIdentity(); try { @@ -526,7 +525,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public boolean requestScores(NetworkKey[] networks) { - mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); + mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); final long token = Binder.clearCallingIdentity(); try { final INetworkRecommendationProvider provider = getRecommendationProvider(); diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 11e1a9d9b05f..14c65296decc 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -63,8 +63,8 @@ import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.content.pm.UserInfo; import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Environment; @@ -76,6 +76,7 @@ import android.os.Parcel; import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; +import android.os.StrictMode; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; @@ -111,15 +112,16 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; -import java.util.Set; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; @@ -174,17 +176,18 @@ public class AccountManagerService private static final String PRE_N_DATABASE_NAME = "accounts.db"; private static final Intent ACCOUNTS_CHANGED_INTENT; + private static final int SIGNATURE_CHECK_MISMATCH = 0; + private static final int SIGNATURE_CHECK_MATCH = 1; + private static final int SIGNATURE_CHECK_UID_MATCH = 2; + static { ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION); ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); } - private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>(); private final AtomicInteger mNotificationIds = new AtomicInteger(1); - private static final String NEW_ACCOUNT_VISIBLE = "android.accounts.NEW_ACCOUNT_VISIBLE"; - static class UserAccounts { private final int userId; final AccountsDb accountsDb; @@ -204,6 +207,10 @@ public class AccountManagerService /** protected by the {@link #cacheLock} */ private final TokenCache accountTokenCaches = new TokenCache(); + /** protected by the {@link #cacheLock} */ + private final Map<String, LinkedHashSet<String>> + mApplicationAccountRequestMappings = new HashMap<>(); + /** * protected by the {@link #cacheLock} * @@ -285,7 +292,26 @@ public class AccountManagerService @Override public void run() { purgeOldGrantsAll(); - // TODO remove visibility entries. + int uidOfUninstalledApplication = + intent.getIntExtra(Intent.EXTRA_UID, -1); + /* remove visibility data for UID */ + if (uidOfUninstalledApplication != -1) { + UserAccounts ua = getUserAccounts(UserHandle + .getUserId(uidOfUninstalledApplication)); + // Stop sending notifications about accounts change to uninstalled + // application. + Uri intentData = intent.getData(); + String packageName = intentData != null + ? intentData.getSchemeSpecificPart() : null; + unregisterAccountTypesSupported(packageName, ua); + String[] allPackages = mPackageManager + .getPackagesForUid(uidOfUninstalledApplication); + // Check that there are no other packages that share uid. + if (allPackages == null) { + deleteAccountVisibilityForUid(uidOfUninstalledApplication, ua); + } + } + } }; mHandler.post(purgingRunnable); @@ -310,7 +336,8 @@ public class AccountManagerService registerAccountTypesSupported( uidOfInstalledApplication, getUserAccounts( - UserHandle.getUserId(uidOfInstalledApplication))); + UserHandle.getUserId(uidOfInstalledApplication)), + true /*notify*/); } } }); @@ -380,11 +407,13 @@ public class AccountManagerService final long identity = Binder.clearCallingIdentity(); try { for (String packageName : packageNames) { - if (mPackageManager.checkPermission( - Manifest.permission.GET_ACCOUNTS, packageName) - != PackageManager.PERMISSION_GRANTED) { - continue; - } + // if app asked for permission we need to cancel notification even + // for O+ applications. + if (mPackageManager.checkPermission( + Manifest.permission.GET_ACCOUNTS, + packageName) != PackageManager.PERMISSION_GRANTED) { + continue; + } if (accounts == null) { accounts = getAccountsAsUser(null, userId, "android"); @@ -405,6 +434,10 @@ public class AccountManagerService }); } + private boolean deleteAccountVisibilityForUid(int uid, UserAccounts accounts) { + return accounts.accountsDb.deleteAccountVisibilityForUid(uid); + } + private void cancelAccountAccessRequestNotificationIfNeeded(int uid, boolean checkAccess) { Account[] accounts = getAccountsAsUser(null, UserHandle.getUserId(uid), "android"); @@ -443,22 +476,95 @@ public class AccountManagerService } @Override - public boolean addAccountExplicitlyWithVisibility(Account account, String password, Bundle extras, - Map uidToVisibility) { - // TODO implementation - return false; + public boolean addAccountExplicitlyWithVisibility(Account account, String password, + Bundle extras, Map uidToVisibility) { + Bundle.setDefusable(extras, true); + + final int callingUid = Binder.getCallingUid(); + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + callingUid + + ", pid " + Binder.getCallingPid()); + } + Preconditions.checkNotNull(account, "account cannot be null"); + int userId = UserHandle.getCallingUserId(); + if (!isAccountManagedByCaller(account.type, callingUid, userId)) { + String msg = String.format("uid %s cannot explicitly add accounts of type: %s", + callingUid, account.type); + throw new SecurityException(msg); + } + /* + * Child users are not allowed to add accounts. Only the accounts that are shared by the + * parent profile can be added to child profile. + * + * TODO: Only allow accounts that were shared to be added by a limited user. + */ + // fails if the account already exists + long identityToken = clearCallingIdentity(); + try { + UserAccounts accounts = getUserAccounts(userId); + return addAccountInternal(accounts, account, password, extras, callingUid, + (Map<Integer, Integer>) uidToVisibility); + } finally { + restoreCallingIdentity(identityToken); + } } @Override public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName, String accountType) { - // TODO Implement. - return new HashMap<Account, Integer>(); + int callingUid = Binder.getCallingUid(); + List<String> managedTypes = + getTypesManagedByCaller(callingUid, UserHandle.getUserId(callingUid)); + if ((accountType != null && !managedTypes.contains(accountType)) + || (accountType == null && !UserHandle.isSameApp(callingUid, Process.SYSTEM_UID))) { + throw new SecurityException( + "getAccountsAndVisibilityForPackage() called from unauthorized uid " + + callingUid + " with packageName=" + packageName); + } + if (accountType != null) { + managedTypes = new ArrayList<String>(); + managedTypes.add(accountType); + } + + return getAccountsAndVisibilityForPackage(packageName, managedTypes, callingUid, + getUserAccounts(UserHandle.getUserId(callingUid))); } + /* + * accountTypes may not be null + */ + private Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName, + List<String> accountTypes, Integer callingUid, UserAccounts accounts) { + int uid = 0; + try { + uid = mPackageManager.getPackageUidAsUser(packageName, + UserHandle.getUserId(callingUid)); + } catch (NameNotFoundException e) { + Log.d("Package not found ", e.getMessage()); + return new HashMap<>(); + } + + Map<Account, Integer> result = new HashMap<>(); + for (String accountType : accountTypes) { + synchronized (accounts.cacheLock) { + final Account[] accountsOfType = accounts.accountCache.get(accountType); + if (accountsOfType != null) { + for (Account account : accountsOfType) { + result.put(account, + resolveAccountVisibility(account, uid, packageName, accounts)); + } + } + } + } + return filterSharedAccounts(accounts, result, callingUid, packageName); + } + + @Override public int[] getRequestingUidsForType(String accountType) { int callingUid = Binder.getCallingUid(); + UserAccounts accounts = getUserAccounts( + UserHandle.getUserId(callingUid)); if (!isAccountManagedByCaller(accountType, callingUid, UserHandle.getUserId(callingUid))) { String msg = String.format( "uid %s cannot get secrets for accounts of type: %s", @@ -466,33 +572,287 @@ public class AccountManagerService accountType); throw new SecurityException(msg); } - // TODO Implement. - return new int[]{}; + LinkedHashSet<String> allUidsForAccountType = getRequestingPackageNames(accountType, accounts); + LinkedHashSet<Integer> uids = new LinkedHashSet<Integer>(); + for (String packageName : allUidsForAccountType) { + try { + int uid = mPackageManager.getPackageUid(packageName, 0); + uids.add(uid); + } catch (NameNotFoundException e) { + Log.d("Package not found ", e.getMessage()); + // Skip bad package. + } + } + // Add UIDs for which visibility was saved in the database. + synchronized (accounts.cacheLock) { + final Account[] accountsOfType = accounts.accountCache.get(accountType); + if (accountsOfType != null) { + for (Account account : accountsOfType) { + final long accountId = accounts.accountsDb.findDeAccountId(account); + if (accountId < 0) { + continue; + } + Map<Integer, Integer> uidToVisibility = + accounts.accountsDb.findAccountVisibilityForAccountId(accountId); + uids.addAll(uidToVisibility.keySet()); + } + } + } + uids.remove(AccountManager.DEFAULT_VISIBILITY); + uids.remove(AccountManager.DEFAULT_LEGACY_VISIBILITY); + + // Some UIDs may contain many packages and we need to remove duplicates. + int[] result = new int[uids.size()]; + int index = 0; + for (Integer uid : uids) { + result[index++] = uid; + } + return result; + } + + /** + * Returns all UIDs for applications that requested the account type. This method + * is called indirectly by the Authenticator and AccountManager + * + * @param accountType authenticator would like to know the requesting apps of + * @param accounts UserAccount that currently hosts the account and application + * + * @return ArrayList of all UIDs that support accounts of this + * account type that seek approval (to be used to know which accounts for + * the authenticator to include in addAccountExplicitly). Null if none. + */ + private LinkedHashSet<String> getRequestingPackageNames( + String accountType, + UserAccounts accounts) { + LinkedHashSet<String> apps = accounts.mApplicationAccountRequestMappings.get(accountType); + if (apps == null) { + apps = new LinkedHashSet<>(); + } + return apps; } @Override public int getAccountVisibility(Account a, int uid) { - // TODO Implement. - return 0; + int callingUid = Binder.getCallingUid(); + if (!isAccountManagedByCaller(a.type, callingUid, UserHandle.getUserId(callingUid)) + && !isSystemUid(callingUid)) { + String msg = String.format( + "uid %s cannot get secrets for accounts of type: %s", + callingUid, + a.type); + throw new SecurityException(msg); + } + return getAccountVisibility(a, uid, getUserAccounts(UserHandle.getUserId(callingUid))); + } + + /** + * Method gets visibility for given account and UID from the database + * + * @param account The account to check visibility of + * @param uid UID to check visibility of + * @param accounts UserAccount that currently hosts the account and application + * + * @return Visibility value, AccountManager.VISIBILITY_UNDEFINED if no value was stored. + * + */ + private int getAccountVisibility(Account account, int uid, UserAccounts accounts) { + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + try { + Integer visibility = accounts.accountsDb.findAccountVisibility(account, uid); + return visibility != null ? visibility : AccountManager.VISIBILITY_UNDEFINED; + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } + } + + /** + * Method which handles default values for Account visibility. + * + * @param account The account to check visibility. + * @param uid UID to check visibility. + * @param packageName Package name to check visibility - the method assumes that it has the same + * uid as specified in the parameter. + * @param accounts UserAccount that currently hosts the account and application + * + * @return Visibility value, the method never returns AccountManager.VISIBILITY_UNDEFINED + * + */ + private Integer resolveAccountVisibility(Account account, int uid, String packageName, + UserAccounts accounts) { + + // Always return stored value if it was set. + int visibility = getAccountVisibility(account, uid, accounts); + if (AccountManager.VISIBILITY_UNDEFINED != visibility) { + return visibility; + } + if (isPermittedForPackage(packageName, Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) { + return AccountManager.VISIBILITY_VISIBLE; // User can not revoke visibility for this + // apps. + } + + if (UserHandle.isSameApp(uid, Process.SYSTEM_UID)) { + return AccountManager.VISIBILITY_VISIBLE; + } + int signatureCheckResult = + checkPackageSignature(account.type, uid, UserHandle.getUserId(uid), packageName); + if (signatureCheckResult == SIGNATURE_CHECK_UID_MATCH) { // uid match + return AccountManager.VISIBILITY_VISIBLE; // Authenticator can always see the account + } + + boolean preO = isPreOApplication(packageName); + if ((signatureCheckResult != SIGNATURE_CHECK_MISMATCH) + || (preO && checkGetAccountsPermission(account.type, uid, UserHandle.getUserId(uid), + packageName))) { + // use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature + // match. + visibility = getAccountVisibility(account, AccountManager.DEFAULT_LEGACY_VISIBILITY, + accounts); + if (AccountManager.VISIBILITY_UNDEFINED == visibility) { + visibility = AccountManager.VISIBILITY_USER_MANAGED_VISIBLE; + } + } else { + visibility = getAccountVisibility(account, AccountManager.DEFAULT_VISIBILITY, accounts); + if (AccountManager.VISIBILITY_UNDEFINED == visibility) { + visibility = AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE; + } + } + + return visibility; + } + + /** + * Checks targetSdk for a package; + * + * @param packageName Package Name + * + * @return True if package's target SDK is below {@link android.os.Build.VERSION_CODES#O}, or + * undefined + */ + private boolean isPreOApplication(String packageName) { + try { + ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName, 0); + if (applicationInfo != null) { + int version = applicationInfo.targetSdkVersion; + return version < android.os.Build.VERSION_CODES.O; + } + return true; + } catch (NameNotFoundException e) { + Log.d(TAG, "Package not found " + e.getMessage()); + return true; + } } @Override - public boolean setAccountVisibility(Account a, int uid, int visibility) { - // TODO Implement. - return false; + public boolean setAccountVisibility(Account a, int uid, int newVisibility) { + int callingUid = Binder.getCallingUid(); + if (!isAccountManagedByCaller(a.type, callingUid, UserHandle.getUserId(callingUid)) + && !isSystemUid(callingUid)) { + String msg = String.format( + "uid %s cannot get secrets for accounts of type: %s", + callingUid, + a.type); + throw new SecurityException(msg); + } + return setAccountVisibility(a, uid, getUserAccounts(UserHandle.getUserId(callingUid)), + newVisibility); + } + + /** + * Gives a certain UID, represented a application, access to an account. This method + * is called indirectly by the Authenticator. + * + * @param account Account to update visibility + * @param uid to add visibility of the Account + * @param accounts UserAccount that currently hosts the account and application + * + * @return True if account visibility was changed. + */ + private boolean setAccountVisibility(Account account, int uid, UserAccounts accounts, + int newVisibility) { + synchronized (accounts.cacheLock) { + LinkedHashSet<String> interestedPackages; + if (uid < 0) { + interestedPackages = getRequestingPackageNames(account.type, accounts); + } else { + interestedPackages = new LinkedHashSet<String>(); + String[] subPackages = mPackageManager.getPackagesForUid(uid); + if (subPackages != null) { + Collections.addAll(interestedPackages, subPackages); + } + } + Integer[] interestedPackagesVisibility = new Integer[interestedPackages.size()]; + + final long accountId = accounts.accountsDb.findDeAccountId(account); + if (accountId < 0) { + return false; + } + int index = 0; + for (String packageName : interestedPackages) { + interestedPackagesVisibility[index++] = + resolveAccountVisibility(account, uid, packageName, accounts); + } + + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + if (!accounts.accountsDb.setAccountVisibility(accountId, uid, newVisibility)) { + return false; + } + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } + + index = 0; + for (String packageName : interestedPackages) { + int visibility = resolveAccountVisibility(account, uid, packageName, accounts); + if (visibility != interestedPackagesVisibility[index++]) { + sendNotification(packageName, account); + } + } + return true; + } } /** - * Registers the requested login account types requested by all the applications already - * installed on the device. + * Register application so it can receive + * + * @param accountTypes account types third party app is willing to support + * @param uid of application requesting account visibility. + * @param packageName Package name of the app requesting account updates. + * @param notifyAuthenticator if set to true than authenticators will be notified about the app + * via ACCOUNTS_LISTENER_PACKAGE_INSTALLED + * @param accounts UserAccount that hosts the account and application + */ + private void addRequestedAccountsVisibility(String[] accountTypes, int uid, String packageName, + boolean notifyAuthenticator, UserAccounts accounts) { + synchronized (accounts.cacheLock) { + for (String accountType : accountTypes) { + LinkedHashSet<String> appSet = + accounts.mApplicationAccountRequestMappings.get(accountType); + if (appSet == null) { + appSet = new LinkedHashSet<>(); + appSet.add(packageName); + accounts.mApplicationAccountRequestMappings.put(accountType, appSet); + } else if (!appSet.contains(packageName)) { + appSet.add(packageName); + } + if (notifyAuthenticator) { + notifyAuthenticator(uid, packageName, accountType, accounts); + } + } + } + } + + /** + * Caches SUPPORTED_ACCOUNT_TYPES for already installed applications, so they may receive + * notifications about account changes. */ private void addRequestsForPreInstalledApplications() { List<PackageInfo> allInstalledPackages = mPackageManager.getInstalledPackages(0); - for(PackageInfo pi : allInstalledPackages) { + for (PackageInfo pi : allInstalledPackages) { int currentUid = pi.applicationInfo.uid; - if(currentUid != -1) { + if (currentUid != -1) { registerAccountTypesSupported(currentUid, - getUserAccounts(UserHandle.getUserId(currentUid))); + getUserAccounts(UserHandle.getUserId(currentUid)), false /* notify */); } } } @@ -502,49 +862,90 @@ public class AccountManagerService * applications manifest as well as allowing it to opt for notifications. * * @param uid UID of application - * @param ua UserAccount that currently hosts the account and application + * @param accounts UserAccount that currently hosts the account and application */ - private void registerAccountTypesSupported(int uid, UserAccounts ua) { + private void registerAccountTypesSupported(int uid, UserAccounts accounts, boolean notify) { /* Account types supported are drawn from the Android Manifest of the Application */ - String interestedPackages = null; + String interestedTypes = null; try { String[] allPackages = mPackageManager.getPackagesForUid(uid); if (allPackages != null) { - for (String aPackage : allPackages) { + for(String aPackage : allPackages) { ApplicationInfo ai = mPackageManager.getApplicationInfo(aPackage, PackageManager.GET_META_DATA); Bundle b = ai.metaData; - if (b == null) { + if(b == null) { return; } - interestedPackages = b.getString(AccountManager.SUPPORTED_ACCOUNT_TYPES); + interestedTypes = b.getString(AccountManager.SUPPORTED_ACCOUNT_TYPES); + if(interestedTypes != null) { + addRequestedAccountsVisibility( + interestedTypes.split(";"), uid, aPackage, notify, accounts); + } + } } - } catch (PackageManager.NameNotFoundException e) { - Log.d("NameNotFoundException", e.getMessage()); + } catch (NameNotFoundException e) { + Log.d("Package not found ", e.getMessage()); } - if (interestedPackages != null) { - // TODO request visibility - // requestAccountVisibility(interestedPackages.split(";"), uid, ua); + } + + private void unregisterAccountTypesSupported(String packageName, UserAccounts accounts) { + synchronized(accounts.cacheLock) { + for (HashSet<String> packages : accounts.mApplicationAccountRequestMappings.values()) { + packages.remove(packageName); + } } } /** * Sends a direct intent to a package, notifying it of a visible account change. * - * @param desiredPackage to send Account to - * @param visibleAccount to send to package + * @param packageName to send Account to + * @param account to send to package */ - private void sendNotification(String desiredPackage, Account visibleAccount) { + private void sendNotification(String packageName, Account account) { + // TODO remove account param? Intent intent = new Intent(); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.setAction(AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED); - intent.setPackage(desiredPackage); - // TODO update documentation, add account extra if new account became visible - // intent.putExtra("android.accounts.KEY_ACCOUNT", (Account) visibleAccount); + intent.setPackage(packageName); + // intent.putExtra("android.accounts.KEY_ACCOUNT", (Account) account); mContext.sendBroadcast(intent); } + /** + * Sends a direct intent to accountAuthenticator, signaling that new app with supported + * accountType is installed. + * + * @param uid UID + * @param newPackage Package Name + * @param accounts UserAccount that currently hosts the account and application + */ + private void notifyAuthenticator(Integer uid, String newPackage, String accountType, + UserAccounts accounts) { + final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo = + mAuthenticatorCache.getServiceInfo(AuthenticatorDescription.newKey(accountType), + accounts.userId); + if (authenticatorInfo == null) { + return; + } + String[] allPackages = mPackageManager.getPackagesForUid(authenticatorInfo.uid); + // There may be packages with shared userId. + if (allPackages != null) { + for (String subPackage : allPackages) { + Intent intent = + new Intent(AccountManager.ACTION_ACCOUNTS_LISTENER_PACKAGE_INSTALLED); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + intent.setPackage(subPackage); + intent.putExtra("android.intent.extra.PACKAGE_NAME", newPackage); + mContext.sendBroadcastAsUser(intent, + UserHandle.getUserHandleForUid(accounts.userId)); + } + + } + } + @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { @@ -786,7 +1187,7 @@ public class AccountManagerService AccountsDb.TABLE_ACCOUNTS); for (Account account : accountsToRemove) { - removeAccountInternal(accounts, account, Process.myUid()); + removeAccountInternal(accounts, account, Process.SYSTEM_UID); } } } @@ -1043,7 +1444,7 @@ public class AccountManagerService private boolean isCrossUser(int callingUid, int userId) { return (userId != UserHandle.getCallingUserId() - && callingUid != Process.myUid() + && callingUid != Process.SYSTEM_UID && mContext.checkCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED); @@ -1051,42 +1452,7 @@ public class AccountManagerService @Override public boolean addAccountExplicitly(Account account, String password, Bundle extras) { - Bundle.setDefusable(extras, true); - // clears the visible list functionality for this account because this method allows - // default account access to all applications for account. - - final int callingUid = Binder.getCallingUid(); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "addAccountExplicitly: " + account - + ", caller's uid " + callingUid - + ", pid " + Binder.getCallingPid()); - } - if (account == null) throw new IllegalArgumentException("account is null"); - int userId = UserHandle.getCallingUserId(); - if (!isAccountManagedByCaller(account.type, callingUid, userId)) { - String msg = String.format( - "uid %s cannot explicitly add accounts of type: %s", - callingUid, - account.type); - throw new SecurityException(msg); - } - - /* - * Child users are not allowed to add accounts. Only the accounts that are - * shared by the parent profile can be added to child profile. - * - * TODO: Only allow accounts that were shared to be added by - * a limited user. - */ - - // fails if the account already exists - long identityToken = clearCallingIdentity(); - try { - UserAccounts accounts = getUserAccounts(userId); - return addAccountInternal(accounts, account, password, extras, callingUid); - } finally { - restoreCallingIdentity(identityToken); - } + return addAccountExplicitlyWithVisibility(account, password, extras, null); } @Override @@ -1227,6 +1593,8 @@ public class AccountManagerService // TODO: Anything to do if if succedded? // TODO: If it failed: Show error notification? Should we remove the shadow // account to avoid retries? + // TODO: what we do with the visibility? + super.onResult(result); } @@ -1244,7 +1612,7 @@ public class AccountManagerService } private boolean addAccountInternal(UserAccounts accounts, Account account, String password, - Bundle extras, int callingUid) { + Bundle extras, int callingUid, Map<Integer, Integer> uidToVisibility) { Bundle.setDefusable(extras, true); if (account == null) { return false; @@ -1284,10 +1652,17 @@ public class AccountManagerService } } } + + if (uidToVisibility != null) { + for (Entry<Integer, Integer> entry : uidToVisibility.entrySet()) { + setAccountVisibility(account, entry.getKey() /* uid */, + entry.getValue() /* visibility */); + } + } accounts.accountsDb.setTransactionSuccessful(); - logRecord(AccountsDb.DEBUG_ACTION_ACCOUNT_ADD, AccountsDb.TABLE_ACCOUNTS, - accountId, accounts, callingUid); + logRecord(AccountsDb.DEBUG_ACTION_ACCOUNT_ADD, AccountsDb.TABLE_ACCOUNTS, accountId, + accounts, callingUid); insertAccountIntoCacheLocked(accounts, account); } finally { @@ -1300,6 +1675,23 @@ public class AccountManagerService // Only send LOGIN_ACCOUNTS_CHANGED when the database changed. sendAccountsChangedBroadcast(accounts.userId); + + // Send ACTION_VISIBLE_ACCOUNT_CHANGE to apps interested in the account type. + LinkedHashSet<String> interestedPackages = getRequestingPackageNames(account.type, + getUserAccounts(UserHandle.getUserId(callingUid))); + for (String packageName : interestedPackages) { + try { + final int uid = mPackageManager.getPackageUidAsUser(packageName, + UserHandle.getUserId(callingUid)); + int visibility = resolveAccountVisibility(account, uid, packageName, accounts); + if (visibility != AccountManager.VISIBILITY_NOT_VISIBLE) { + sendNotification(packageName, account); + } + } catch (NameNotFoundException e) { + // ignore + } + + } return true; } @@ -1727,6 +2119,24 @@ public class AccountManagerService + " is still locked. CE data will be removed later"); } synchronized (accounts.cacheLock) { + LinkedHashSet<String> interestedPackages = + accounts.mApplicationAccountRequestMappings.get(account.type); + if (interestedPackages == null) { + interestedPackages = new LinkedHashSet<String>(); + } + int[] visibilityForInterestedPackages = new int[interestedPackages.size()]; + int index = 0; + for (String packageName : interestedPackages) { + int visibility = AccountManager.VISIBILITY_NOT_VISIBLE; + try { + final int uid = mPackageManager.getPackageUidAsUser(packageName, + UserHandle.getUserId(callingUid)); + visibility = resolveAccountVisibility(account, uid, packageName, accounts); + } catch (NameNotFoundException e) { + // ignore + } + visibilityForInterestedPackages[index++] = visibility; + } accounts.accountsDb.beginTransaction(); // Set to a dummy value, this will only be used if the database // transaction succeeds. @@ -1750,6 +2160,17 @@ public class AccountManagerService } if (isChanged) { removeAccountFromCacheLocked(accounts, account); + index = 0; + for (String packageName : interestedPackages) { + if ((visibilityForInterestedPackages[index] + != AccountManager.VISIBILITY_NOT_VISIBLE) + && (visibilityForInterestedPackages[index] + != AccountManager.VISIBILITY_UNDEFINED)) { + sendNotification(packageName, account); + } + ++index; + } + // Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occured. sendAccountsChangedBroadcast(accounts.userId); String action = userUnlocked ? AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE @@ -2406,8 +2827,10 @@ public class AccountManagerService checkKeyIntent( Binder.getCallingUid(), intent); - doNotification(mAccounts, - account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE), + doNotification( + mAccounts, + account, + result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE), intent, "android", accounts.userId); } } @@ -3292,7 +3715,8 @@ public class AccountManagerService if (response == null) throw new IllegalArgumentException("response is null"); if (accountType == null) throw new IllegalArgumentException("accountType is null"); int userId = UserHandle.getCallingUserId(); - if (!isAccountManagedByCaller(accountType, callingUid, userId) && !isSystemUid(callingUid)) { + if (!isAccountManagedByCaller(accountType, callingUid, userId) + && !isSystemUid(callingUid)) { String msg = String.format( "uid %s cannot edit authenticator properites for account type: %s", callingUid, @@ -3335,23 +3759,50 @@ public class AccountManagerService Preconditions.checkArgumentInRange(userId, 0, Integer.MAX_VALUE, "user must be concrete"); try { - final int uid = mPackageManager.getPackageUidAsUser(packageName, userId); + int uid = mPackageManager.getPackageUidAsUser(packageName, userId); return hasAccountAccess(account, packageName, uid); } catch (NameNotFoundException e) { + Log.d(TAG, "Package not found " + e.getMessage()); return false; } } + // Returns package with oldest target SDK for given UID. + private String getPackageNameForUid(int uid) { + String[] packageNames = mPackageManager.getPackagesForUid(uid); + if (ArrayUtils.isEmpty(packageNames)) { + return null; + } + // For app op checks related to permissions all packages in the UID + // have the same app op state, so doesn't matter which one we pick. + // Update: due to visibility changes we want to use package with oldest target SDK, + + String packageName = packageNames[0]; + int oldestVersion = Integer.MAX_VALUE; + for (String name : packageNames) { + try { + ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(name, 0); + if (applicationInfo != null) { + int version = applicationInfo.targetSdkVersion; + if (version < oldestVersion) { + oldestVersion = version; + packageName = name; + } + } + } catch (NameNotFoundException e) { + // skip + } + } + return packageName; + } + private boolean hasAccountAccess(@NonNull Account account, @Nullable String packageName, int uid) { if (packageName == null) { - String[] packageNames = mPackageManager.getPackagesForUid(uid); - if (ArrayUtils.isEmpty(packageNames)) { + packageName = getPackageNameForUid(uid); + if (packageName == null) { return false; } - // For app op checks related to permissions all packages in the UID - // have the same app op state, so doesn't matter which one we pick. - packageName = packageNames[0]; } // Use null token which means any token. Having a token means the package @@ -3360,9 +3811,12 @@ public class AccountManagerService return true; } // In addition to the permissions required to get an auth token we also allow - // the account to be accessed by holders of the get accounts permissions. - return checkUidPermission(Manifest.permission.GET_ACCOUNTS_PRIVILEGED, uid, packageName) - || checkUidPermission(Manifest.permission.GET_ACCOUNTS, uid, packageName); + // the account to be accessed by apps for which user or authenticator granted visibility. + + int visibility = resolveAccountVisibility(account, uid, packageName, + getUserAccounts(UserHandle.getUserId(uid))); + return (visibility == AccountManager.VISIBILITY_VISIBLE + || visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); } private boolean checkUidPermission(String permission, int uid, String opPackageName) { @@ -3476,21 +3930,28 @@ public class AccountManagerService private volatile ArrayList<Account> mAccountsWithFeatures = null; private volatile int mCurrentAccount = 0; private final int mCallingUid; + private final String mPackageName; - public GetAccountsByTypeAndFeatureSession(UserAccounts accounts, - IAccountManagerResponse response, String type, String[] features, int callingUid) { + public GetAccountsByTypeAndFeatureSession( + UserAccounts accounts, + IAccountManagerResponse response, + String type, + String[] features, + int callingUid, + String packageName) { super(accounts, response, type, false /* expectActivityLaunch */, true /* stripAuthTokenFromResult */, null /* accountName */, false /* authDetailsRequired */); mCallingUid = callingUid; mFeatures = features; + mPackageName = packageName; } @Override public void run() throws RemoteException { synchronized (mAccounts.cacheLock) { mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid, - null); + mPackageName); } // check whether each account matches the requested features mAccountsWithFeatures = new ArrayList<>(mAccountsOfType.length); @@ -3589,7 +4050,7 @@ public class AccountManagerService return getAccountsInternal( accounts, callingUid, - null, // packageName + opPackageName, visibleAccountTypes); } finally { restoreCallingIdentity(identityToken); @@ -3632,7 +4093,7 @@ public class AccountManagerService if (userAccounts == null) continue; synchronized (userAccounts.cacheLock) { Account[] accounts = getAccountsFromCacheLocked(userAccounts, null, - Binder.getCallingUid(), null); + Binder.getCallingUid(), null); //TODO check package for (int a = 0; a < accounts.length; a++) { runningAccounts.add(new AccountAndUser(accounts[a], userId)); } @@ -3646,7 +4107,19 @@ public class AccountManagerService @Override @NonNull public Account[] getAccountsAsUser(String type, int userId, String opPackageName) { - return getAccountsAsUser(type, userId, null, -1, opPackageName); + return getAccountsAsUser(type, userId, null /* callingPackage */, -1, opPackageName); + } + + @NonNull + private Account[] filterVisibleAccounts(Map<Account, Integer> accounts) { + ArrayList<Account> filteredAccounts = new ArrayList<>(); + for (Map.Entry<Account, Integer> entry : accounts.entrySet()) { + if (entry.getValue() == AccountManager.VISIBILITY_VISIBLE + || entry.getValue() == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE) { + filteredAccounts.add(entry.getKey()); + } + } + return filteredAccounts.toArray(new Account[filteredAccounts.size()]); } @NonNull @@ -3659,7 +4132,7 @@ public class AccountManagerService int callingUid = Binder.getCallingUid(); // Only allow the system process to read accounts of other users if (userId != UserHandle.getCallingUserId() - && callingUid != Process.myUid() + && callingUid != Process.SYSTEM_UID && mContext.checkCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED) { @@ -3672,9 +4145,17 @@ public class AccountManagerService + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid()); } - // If the original calling app was using the framework account chooser activity, we'll - // be passed in the original caller's uid here, which is what should be used for filtering. - if (packageUid != -1 && UserHandle.isSameApp(callingUid, Process.myUid())) { + + // If the original calling app was using account choosing activity + // provided by the framework or authenticator we'll passing in + // the original caller's uid here, which is what should be used for filtering. + List<String> managedTypes = + getTypesManagedByCaller(callingUid, UserHandle.getUserId(callingUid)); + if (packageUid != -1 && + ((UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) + || (type != null && managedTypes.contains(type))))) { + Log.v(TAG, "getAccounts package was swithed to " + callingPackage + " from " + + opPackageName); callingUid = packageUid; opPackageName = callingPackage; } @@ -3682,7 +4163,7 @@ public class AccountManagerService opPackageName); if (visibleAccountTypes.isEmpty() || (type != null && !visibleAccountTypes.contains(type))) { - return new Account[0]; + return new Account[]{}; } else if (visibleAccountTypes.contains(type)) { // Prune the list down to just the requested type. visibleAccountTypes = new ArrayList<>(); @@ -3696,7 +4177,7 @@ public class AccountManagerService return getAccountsInternal( accounts, callingUid, - callingPackage, + opPackageName, visibleAccountTypes); } finally { restoreCallingIdentity(identityToken); @@ -3797,6 +4278,7 @@ public class AccountManagerService @Override @NonNull public Account[] getAccounts(String type, String opPackageName) { + Log.v(TAG, "get accounts for package " + opPackageName + " type " + type); return getAccountsAsUser(type, UserHandle.getCallingUserId(), opPackageName); } @@ -3804,7 +4286,7 @@ public class AccountManagerService @NonNull public Account[] getAccountsForPackage(String packageName, int uid, String opPackageName) { int callingUid = Binder.getCallingUid(); - if (!UserHandle.isSameApp(callingUid, Process.myUid())) { + if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) { throw new SecurityException("getAccountsForPackage() called from unauthorized uid " + callingUid + " with uid=" + uid); } @@ -3816,17 +4298,18 @@ public class AccountManagerService @NonNull public Account[] getAccountsByTypeForPackage(String type, String packageName, String opPackageName) { + int packageUid = -1; try { - packageUid = AppGlobals.getPackageManager().getPackageUid( - packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, - UserHandle.getCallingUserId()); + packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, + PackageManager.MATCH_UNINSTALLED_PACKAGES, UserHandle.getCallingUserId()); } catch (RemoteException re) { Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re); return new Account[0]; } - return getAccountsAsUser(type, UserHandle.getCallingUserId(), packageName, - packageUid, opPackageName); + + return getAccountsAsUser(type, UserHandle.getCallingUserId(), + packageName, packageUid, opPackageName); } @Override @@ -3866,7 +4349,8 @@ public class AccountManagerService if (features == null || features.length == 0) { Account[] accounts; synchronized (userAccounts.cacheLock) { - accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid, null); + accounts = getAccountsFromCacheLocked( + userAccounts, type, callingUid, opPackageName); } Bundle result = new Bundle(); result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts); @@ -3878,7 +4362,8 @@ public class AccountManagerService response, type, features, - callingUid).bind(); + callingUid, + opPackageName).bind(); } finally { restoreCallingIdentity(identityToken); } @@ -3897,6 +4382,7 @@ public class AccountManagerService if (Objects.equals(account.getAccessId(), token)) { // An app just accessed the account. At this point it knows about // it and there is not need to hide this account from the app. + // Do we need to update account visibility here? if (!hasAccountAccess(account, null, uid)) { updateAppPermission(account, AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid, true); @@ -4423,7 +4909,7 @@ public class AccountManagerService userAccounts.accountsDb.dumpDeAccountsTable(fout); } else { Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */, - Process.myUid(), null); + Process.SYSTEM_UID, null); fout.println("Accounts: " + accounts.length); for (Account account : accounts) { fout.println(" " + account); @@ -4516,6 +5002,16 @@ public class AccountManagerService } } + private boolean isPermittedForPackage(String opPackageName, String... permissions) { + for (String perm : permissions) { + if (mPackageManager.checkPermission(perm, opPackageName) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + } + return false; + } + private boolean isPermitted(String opPackageName, int callingUid, String... permissions) { for (String perm : permissions) { if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) { @@ -4550,6 +5046,7 @@ public class AccountManagerService userPackageManager = mContext.createPackageContextAsUser( "android", 0, new UserHandle(callingUserId)).getPackageManager(); } catch (NameNotFoundException e) { + Log.d(TAG, "Package not found " + e.getMessage()); return false; } @@ -4563,6 +5060,7 @@ public class AccountManagerService return true; } } catch (PackageManager.NameNotFoundException e) { + Log.d(TAG, "Package not found " + e.getMessage()); return false; } } @@ -4617,6 +5115,58 @@ public class AccountManagerService } } + // Method checks visibility for applications targeing API level below {@link + // android.os.Build.VERSION_CODES#O}, + // returns true if the the app has GET_ACCOUNTS or GET_ACCOUNTS_PRIVELEGED permission. + private boolean checkGetAccountsPermission(String accountType, int callingUid, int userId, + String opPackageName) { + if (accountType == null) { + return false; + } + if (isPermittedForPackage(opPackageName, Manifest.permission.GET_ACCOUNTS, + Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) { + return true; + } + + return false; + } + + /** + * Method checks package uid and signature with Authenticator which manages accountType. + * + * @return SIGNATURE_CHECK_UID_MATCH for uid match, SIGNATURE_CHECK_MATCH for signature match, + * SIGNATURE_CHECK_MISMATCH otherwise. + */ + private int checkPackageSignature(String accountType, int callingUid, int userId, + String opPackageName) { + if (accountType == null) { + return SIGNATURE_CHECK_MISMATCH; + } + + long identityToken = Binder.clearCallingIdentity(); + Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> serviceInfos; + try { + serviceInfos = mAuthenticatorCache.getAllServices(userId); + } finally { + Binder.restoreCallingIdentity(identityToken); + } + // Check for signtaure match with Authenticator. + for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo + : serviceInfos) { + if (accountType.equals(serviceInfo.type.type)) { + if (serviceInfo.uid == callingUid) { + return SIGNATURE_CHECK_UID_MATCH; + } + final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid); + if (sigChk == PackageManager.SIGNATURE_MATCH) { + return SIGNATURE_CHECK_MATCH; + } + } + } + return SIGNATURE_CHECK_MISMATCH; + } + + // returns true for system apps and applications with the same signature as authenticator. private boolean isAccountManagedByCaller(String accountType, int callingUid, int userId) { if (accountType == null) { return false; @@ -4627,14 +5177,13 @@ public class AccountManagerService private List<String> getTypesVisibleToCaller(int callingUid, int userId, String opPackageName) { - boolean isPermitted = - isPermitted(opPackageName, callingUid, Manifest.permission.GET_ACCOUNTS, - Manifest.permission.GET_ACCOUNTS_PRIVILEGED); - return getTypesForCaller(callingUid, userId, isPermitted); + return getTypesForCaller(callingUid, userId, true /* isOtherwisePermitted*/); } private List<String> getTypesManagedByCaller(int callingUid, int userId) { - return getTypesForCaller(callingUid, userId, false); + // System UID is considered priveleged, GET_ACCOUNTS_PRIVILEGED is not enough. + boolean isPrivileged = UserHandle.isSameApp(callingUid, Process.SYSTEM_UID); + return getTypesForCaller(callingUid, userId, isPrivileged); } private List<String> getTypesForCaller( @@ -4649,8 +5198,9 @@ public class AccountManagerService } for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo : serviceInfos) { - final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid); - if (isOtherwisePermitted || sigChk == PackageManager.SIGNATURE_MATCH) { + if (isOtherwisePermitted || (serviceInfo.uid == callingUid) + || (mPackageManager.checkSignatures(serviceInfo.uid, callingUid + ) == PackageManager.SIGNATURE_MATCH)) { managedAccountTypes.add(serviceInfo.type.type); } } @@ -4732,7 +5282,7 @@ public class AccountManagerService != 0) { return true; } - } catch (PackageManager.NameNotFoundException e) { + } catch (NameNotFoundException e) { Log.w(TAG, String.format("Could not find package [%s]", name), e); } } @@ -4923,10 +5473,31 @@ public class AccountManagerService return newAccountsForType[oldLength]; } - private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered, - int callingUid, String callingPackage) { + private Account[] filterAccounts(UserAccounts accounts, Account[] unfiltered, int callingUid, + String callingPackage) { + Map<Account, Integer> firstPass = new HashMap<>(); + for (Account account : unfiltered) { + int visibility = + resolveAccountVisibility(account, callingUid, callingPackage, accounts); + if (visibility == AccountManager.VISIBILITY_VISIBLE + || visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE) { + firstPass.put(account, visibility); + } + } + Map<Account, Integer> secondPass = + filterSharedAccounts(accounts, firstPass, callingUid, callingPackage); + + Account[] filtered = new Account[secondPass.size()]; + filtered = secondPass.keySet().toArray(filtered); + return filtered; + } + + private Map<Account, Integer> filterSharedAccounts(UserAccounts userAccounts, + Map<Account, Integer> unfiltered, int callingUid, String callingPackage) { + // first part is to filter shared accounts. + // unfiltered type check is not necessary. if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0 - || callingUid == Process.myUid()) { + || callingUid == Process.SYSTEM_UID) { return unfiltered; } UserInfo user = getUserManager().getUserInfo(userAccounts.userId); @@ -4944,7 +5515,9 @@ public class AccountManagerService } ArrayList<Account> allowed = new ArrayList<>(); Account[] sharedAccounts = getSharedAccountsAsUser(userAccounts.userId); - if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered; + if (ArrayUtils.isEmpty(sharedAccounts)) { + return unfiltered; + } String requiredAccountType = ""; try { // If there's an explicit callingPackage specified, check if that package @@ -4964,9 +5537,12 @@ public class AccountManagerService } } } - } catch (NameNotFoundException nnfe) { + } catch (NameNotFoundException e) { + Log.d(TAG, "Package not found " + e.getMessage()); } - for (Account account : unfiltered) { + Map<Account, Integer> filtered = new HashMap<>(); + for (Map.Entry<Account, Integer> entry : unfiltered.entrySet()) { + Account account = entry.getKey(); if (account.type.equals(requiredAccountType)) { allowed.add(account); } else { @@ -4978,12 +5554,10 @@ public class AccountManagerService } } if (!found) { - allowed.add(account); + filtered.put(account, entry.getValue()); } } } - Account[] filtered = new Account[allowed.size()]; - allowed.toArray(filtered); return filtered; } else { return unfiltered; @@ -5001,7 +5575,7 @@ public class AccountManagerService if (accounts == null) { return EMPTY_ACCOUNT_ARRAY; } else { - return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length), + return filterAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length), callingUid, callingPackage); } } else { @@ -5019,7 +5593,7 @@ public class AccountManagerService accountsOfType.length); totalLength += accountsOfType.length; } - return filterSharedAccounts(userAccounts, accounts, callingUid, callingPackage); + return filterAccounts(userAccounts, accounts, callingUid, callingPackage); } } @@ -5247,19 +5821,21 @@ public class AccountManagerService if (userId == 0) { // Migrate old file, if it exists, to the new location. // Make sure the new file doesn't already exist. A dummy file could have been - // accidentally created in the old location, causing the new one to become corrupted - // as well. + // accidentally created in the old location, + // causing the new one to become corrupted as well. File oldFile = new File(systemDir, PRE_N_DATABASE_NAME); if (oldFile.exists() && !databaseFile.exists()) { // Check for use directory; create if it doesn't exist, else renameTo will fail File userDir = Environment.getUserSystemDirectory(userId); if (!userDir.exists()) { if (!userDir.mkdirs()) { - throw new IllegalStateException("User dir cannot be created: " + userDir); + throw new IllegalStateException( + "User dir cannot be created: " + userDir); } } if (!oldFile.renameTo(databaseFile)) { - throw new IllegalStateException("User dir cannot be migrated: " + databaseFile); + throw new IllegalStateException( + "User dir cannot be migrated: " + databaseFile); } } } diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java index 5ca74711ddbb..0ee20ccea2eb 100644 --- a/services/core/java/com/android/server/accounts/AccountsDb.java +++ b/services/core/java/com/android/server/accounts/AccountsDb.java @@ -355,7 +355,7 @@ class AccountsDb implements AutoCloseable { boolean deleteAuthtokensByAccountIdAndType(long accountId, String authtokenType) { SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked(); return db.delete(CE_TABLE_AUTHTOKENS, - AUTHTOKENS_ACCOUNTS_ID + "=?" + accountId + " AND " + AUTHTOKENS_TYPE + "=?", + AUTHTOKENS_ACCOUNTS_ID + "=?" + " AND " + AUTHTOKENS_TYPE + "=?", new String[]{String.valueOf(accountId), authtokenType}) > 0; } @@ -1306,4 +1306,4 @@ class AccountsDb implements AutoCloseable { return new AccountsDb(deDatabaseHelper, context, preNDatabaseFile); } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 32dec96c027e..3f166fe4ddfb 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -17,6 +17,7 @@ import android.content.Context; import android.os.SystemClock; import android.util.Slog; +import com.android.internal.logging.LogBuilder; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -170,6 +171,13 @@ class ActivityMetricsLogger { processRunning); MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS, (int) (SystemClock.uptimeMillis() / 1000)); + + LogBuilder builder = new LogBuilder(); + builder.addTaggedData(MetricsEvent.APP_TRANSITION_COMPONENT_NAME, componentName); + builder.addTaggedData(MetricsEvent.APP_TRANSITION_PROCESS_RUNNING, processRunning ? 1 : 0); + builder.addTaggedData(MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS, + SystemClock.uptimeMillis() / 1000); + MetricsLogger.action(builder); } /** diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index ddef339caa5d..f7c3cea2eed6 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1390,24 +1390,6 @@ final class ActivityStack extends ConfigurationContainer { return null; } - ActivityStack getNextFocusableStackLocked() { - ArrayList<ActivityStack> stacks = mStacks; - final ActivityRecord parent = mActivityContainer.mParentActivity; - if (parent != null) { - stacks = parent.getStack().mStacks; - } - if (stacks != null) { - for (int i = stacks.size() - 1; i >= 0; --i) { - ActivityStack stack = stacks.get(i); - if (stack != this && stack.isFocusable() - && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) { - return stack; - } - } - } - return null; - } - /** Returns true if the stack contains a fullscreen task. */ private boolean hasFullscreenTask() { for (int i = mTaskHistory.size() - 1; i >= 0; --i) { @@ -2098,9 +2080,15 @@ final class ActivityStack extends ConfigurationContainer { return false; } - ActivityRecord parent = mActivityContainer.mParentActivity; - if ((parent != null && parent.state != ActivityState.RESUMED) || - !mActivityContainer.isAttachedLocked()) { + // Find the topmost activity in this stack that is not finishing. + final ActivityRecord next = topRunningActivityLocked(); + + final boolean hasRunningActivity = next != null; + + final ActivityRecord parent = mActivityContainer.mParentActivity; + final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED; + if (hasRunningActivity + && (isParentNotResumed || !mActivityContainer.isAttachedLocked())) { // Do not resume this stack if its parent is not resumed. // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st. return false; @@ -2108,33 +2096,14 @@ final class ActivityStack extends ConfigurationContainer { mStackSupervisor.cancelInitializingActivities(); - // Find the first activity that is not finishing. - final ActivityRecord next = topRunningActivityLocked(); - // Remember how we'll process this pause/resume situation, and ensure // that the state is reset however we wind up proceeding. final boolean userLeaving = mStackSupervisor.mUserLeaving; mStackSupervisor.mUserLeaving = false; - final TaskRecord prevTask = prev != null ? prev.task : null; - if (next == null) { - // There are no more activities! - final String reason = "noMoreActivities"; - if (!mFullscreen && adjustFocusToNextFocusableStackLocked(reason)) { - // Try to move focus to the next visible stack with a running activity if this - // stack is not covering the entire screen. - return mStackSupervisor.resumeFocusedStackTopActivityLocked( - mStackSupervisor.getFocusedStack(), prev, null); - } - - // Let's just start up the Launcher... - ActivityOptions.abort(options); - if (DEBUG_STATES) Slog.d(TAG_STATES, - "resumeTopActivityLocked: No more activities go home"); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); - // Only resume home if on home display - return isOnHomeDisplay() && - mStackSupervisor.resumeHomeStackTask(prev, reason); + if (!hasRunningActivity) { + // There are no activities left in the stack, let's look somewhere else. + return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities"); } next.delayedResume = false; @@ -2152,6 +2121,7 @@ final class ActivityStack extends ConfigurationContainer { } final TaskRecord nextTask = next.task; + final TaskRecord prevTask = prev != null ? prev.task : null; if (prevTask != null && prevTask.getStack() == this && prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); @@ -2527,6 +2497,27 @@ final class ActivityStack extends ConfigurationContainer { return true; } + private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev, + ActivityOptions options, String reason) { + if ((!mFullscreen || !isOnHomeDisplay()) + && adjustFocusToNextFocusableStackLocked(reason)) { + // Try to move focus to the next visible stack with a running activity if this + // stack is not covering the entire screen or is on a secondary display (with no home + // stack). + return mStackSupervisor.resumeFocusedStackTopActivityLocked( + mStackSupervisor.getFocusedStack(), prev, null); + } + + // Let's just start up the Launcher... + ActivityOptions.abort(options); + if (DEBUG_STATES) Slog.d(TAG_STATES, + "resumeTopActivityInNextFocusableStack: " + reason + ", go home"); + if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); + // Only resume home if on home display + return isOnHomeDisplay() && + mStackSupervisor.resumeHomeStackTask(prev, reason); + } + private TaskRecord getNextTask(TaskRecord targetTask) { final int index = mTaskHistory.indexOf(targetTask); if (index >= 0) { @@ -3151,7 +3142,7 @@ final class ActivityStack extends ConfigurationContainer { } private boolean adjustFocusToNextFocusableStackLocked(String reason) { - final ActivityStack stack = getNextFocusableStackLocked(); + final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked(this); final String myReason = reason + " adjustFocusToNextFocusableStack"; if (stack == null) { return false; diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 8ab3ac39dd5b..5def3403dc56 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -455,6 +455,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private final FindTaskResult mTmpFindTaskResult = new FindTaskResult(); /** + * Temp storage for display ids sorted in focus order. + * Maps position to id. Using {@link SparseIntArray} instead of {@link ArrayList} because + * it's more efficient, as the number of displays is usually small. + */ + private SparseIntArray mTmpOrderedDisplayIds = new SparseIntArray(); + + /** * Used to keep track whether app visibilities got changed since the last pause. Useful to * determine whether to invoke the task stack change listener after pausing. */ @@ -637,7 +644,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) { if (!focusCandidate.isFocusable()) { // The focus candidate isn't focusable. Move focus to the top stack that is focusable. - focusCandidate = focusCandidate.getNextFocusableStackLocked(); + focusCandidate = getNextFocusableStackLocked(focusCandidate); } if (focusCandidate != mFocusedStack) { @@ -2019,6 +2026,35 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return mActivityDisplays.valueAt(DEFAULT_DISPLAY).mStacks; } + /** + * Get next focusable stack in the system. This will search across displays and stacks + * in last-focused order for a focusable and visible stack, different from the target stack. + * + * @param currentFocus The stack that previously had focus and thus needs to be ignored when + * searching for next candidate. + * @return Next focusable {@link ActivityStack}, null if not found. + */ + ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) { + mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds); + + for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) { + final int displayId = mTmpOrderedDisplayIds.get(i); + final List<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks; + if (stacks == null) { + continue; + } + for (int j = stacks.size() - 1; j >= 0; --j) { + final ActivityStack stack = stacks.get(j); + if (stack != currentFocus && stack.isFocusable() + && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) { + return stack; + } + } + } + + return null; + } + ActivityRecord getHomeActivity() { return getHomeActivityForUser(mCurrentUser); } diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 3bb9ccc22a87..09af9412da64 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1238,7 +1238,7 @@ class ActivityStarter { r.mTaskOverlay = true; final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId()); final ActivityRecord top = task != null ? task.getTopActivity() : null; - if (top != null && !top.visible) { + if (top != null && top.state != RESUMED) { // The caller specifies that we'd like to be avoided to be moved to the front, so be // it! diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 0ea78b3e9e83..f1f8bb20652d 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -991,7 +991,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public void setBatteryState(final int status, final int health, final int plugType, - final int level, final int temp, final int volt, final int chargeUAh) { + final int level, final int temp, final int volt, final int chargeUAh, + final int chargeFullUAh) { enforceCallingPermission(); // BatteryService calls us here and we may update external state. It would be wrong @@ -1005,7 +1006,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub // The battery state has not changed, so we don't need to sync external // stats immediately. mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt, - chargeUAh); + chargeUAh, chargeFullUAh); return; } } @@ -1015,7 +1016,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub updateExternalStatsSync("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); synchronized (mStats) { mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt, - chargeUAh); + chargeUAh, chargeFullUAh); } } }); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 4d8e26f6955b..dffe86ab47b4 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1552,7 +1552,7 @@ public class NotificationManagerService extends SystemService { public void updateNotificationChannelForPackage(String pkg, int uid, NotificationChannel channel) { enforceSystemOrSystemUI("Caller not system or systemui"); - if (!channel.isAllowed()) { + if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) { // cancel cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true, UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, @@ -2441,7 +2441,7 @@ public class NotificationManagerService extends SystemService { public void updateNotificationChannelFromAssistant(INotificationListener token, String pkg, NotificationChannel channel) throws RemoteException { ManagedServiceInfo info = mNotificationAssistants.checkServiceTokenLocked(token); - if (!channel.isAllowed()) { + if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) { // cancel cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true, info.userid, REASON_CHANNEL_BANNED, null); @@ -2985,7 +2985,7 @@ public class NotificationManagerService extends SystemService { } final boolean isBlocked = r.getImportance() == NotificationManager.IMPORTANCE_NONE - || !r.getChannel().isAllowed() + || r.getChannel().getImportance() == NotificationManager.IMPORTANCE_NONE || !noteNotificationOp(pkg, callingUid); if (isBlocked) { Slog.e(TAG, "Suppressing notification from package by user request."); diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 0c9e4b82189e..598ac2edf5b1 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -445,7 +445,6 @@ public class RankingHelper implements RankingConfig { channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX); channel.setLockscreenVisibility(r.visibility); } - channel.setAllowed(true); clearLockedFields(channel); if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) { channel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE); @@ -516,9 +515,6 @@ public class RankingHelper implements RankingConfig { channel.setLockscreenVisibility(updatedChannel.getLockscreenVisibility()); } } - if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_ALLOWED) == 0) { - channel.setAllowed(updatedChannel.isAllowed()); - } if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SHOW_BADGE) == 0) { channel.setShowBadge(updatedChannel.canShowBadge()); } diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index 00e45fd9b0bc..95023daae096 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -1000,7 +1000,7 @@ final class DefaultPermissionGrantPolicy { permissions.clear(); } permissions.add(permissionGrant.name); - grantRuntimePermissionsLPw(pkg, permissions, false, + grantRuntimePermissionsLPw(pkg, permissions, permissionGrant.fixed, userId); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 92ea2a6ab827..5bb8c05c1be5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2640,19 +2640,6 @@ public class PackageManagerService extends IPackageManager.Stub { mPackageUsage.read(mPackages); mCompilerStats.read(); - // Read and update the usage of dex files. - // At this point we know the code paths of the packages, so we can validate - // the disk file and build the internal cache. - // The usage file is expected to be small so loading and verifying it - // should take a fairly small time compare to the other activities (e.g. package - // scanning). - final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>(); - final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); - for (int userId : currentUserIds) { - userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList()); - } - mDexManager.load(userPackages); - EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis()); Slog.i(TAG, "Time to scan packages: " @@ -2810,6 +2797,21 @@ public class PackageManagerService extends IPackageManager.Stub { } mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this); + + // Read and update the usage of dex files. + // Do this at the end of PM init so that all the packages have their + // data directory reconciled. + // At this point we know the code paths of the packages, so we can validate + // the disk file and build the internal cache. + // The usage file is expected to be small so loading and verifying it + // should take a fairly small time compare to the other activities (e.g. package + // scanning). + final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>(); + final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); + for (int userId : currentUserIds) { + userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList()); + } + mDexManager.load(userPackages); } // synchronized (mPackages) } // synchronized (mInstallLock) diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index b74506229ff7..ddbc5fa59e16 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -259,11 +259,6 @@ class ShortcutPackage extends ShortcutPackageItem { for (int i = mShortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = mShortcuts.valueAt(i); - if (si.isFloating()) { - si.setRank(0); - si.setActivity(null); - } - if (si.isAlive()) continue; if (removeList == null) { @@ -293,7 +288,6 @@ class ShortcutPackage extends ShortcutPackageItem { si.setTimestamp(now); si.clearFlags(ShortcutInfo.FLAG_DYNAMIC); si.setRank(0); // It may still be pinned, so clear the rank. - si.setActivity(null); } } if (changed) { @@ -361,7 +355,6 @@ class ShortcutPackage extends ShortcutPackageItem { if (oldShortcut.isPinned()) { oldShortcut.setRank(0); - oldShortcut.setActivity(null); oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST); if (disable) { oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED); @@ -602,10 +595,6 @@ class ShortcutPackage extends ShortcutPackageItem { for (int i = mShortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = mShortcuts.valueAt(i); - - if (si.isFloating()) { - continue; // Ignore floating shortcuts, which are not tied to any activities. - } final ComponentName activity = si.getActivity(); if (checked.contains(activity)) { @@ -1368,10 +1357,6 @@ class ShortcutPackage extends ShortcutPackageItem { case TAG_SHORTCUT: final ShortcutInfo si = parseShortcut(parser, packageName, shortcutUser.getUserId()); - // Floating shortcut used to have target activities, but not anymore. - if (si.isFloating()) { // Not really needed by just in case. - si.setActivity(null); - } // Don't use addShortcut(), we don't need to save the icon. ret.mShortcuts.put(si.getId(), si); @@ -1478,6 +1463,7 @@ class ShortcutPackage extends ShortcutPackageItem { intents.clear(); intents.add(intentLegacy); } + return new ShortcutInfo( userId, id, packageName, activityComponent, /* icon =*/ null, title, titleResId, titleResName, text, textResId, textResName, @@ -1568,17 +1554,12 @@ class ShortcutPackage extends ShortcutPackageItem { Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId() + " is both dynamic and manifest at the same time."); } - if (!si.isFloating() && si.getActivity() == null) { - failed = true; - Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId() - + " is not floating, but has null activity."); - } - if (si.isFloating() && si.getActivity() != null) { + if (si.getActivity() == null) { failed = true; Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId() - + " is floating, but has non-null activity."); + + " has null activity."); } - if (!si.isFloating() && !si.isEnabled()) { + if ((si.isDynamic() || si.isManifestShortcut()) && !si.isEnabled()) { failed = true; Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId() + " is not floating, but is disabled."); @@ -1601,7 +1582,7 @@ class ShortcutPackage extends ShortcutPackageItem { } if (failed) { - mShortcutUser.mService.verifyError(); + throw new IllegalStateException("See logcat for errors"); } } diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 86f755694f43..c02ce6e0daeb 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -129,7 +129,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Predicate; @@ -413,9 +412,6 @@ public class ShortcutService extends IShortcutService.Stub { @VisibleForTesting ShortcutService(Context context, Looper looper, boolean onlyForPackageManagerApis) { - if (DEBUG) { - Binder.LOG_RUNTIME_EXCEPTION = true; - } mContext = Preconditions.checkNotNull(context); LocalServices.addService(ShortcutServiceInternal.class, new LocalService()); mHandler = new Handler(looper); @@ -1778,9 +1774,6 @@ public class ShortcutService extends IShortcutService.Stub { // Note copyNonNullFieldsFrom() does the "updatable with?" check too. target.copyNonNullFieldsFrom(source); - if (target.isFloating()) { - target.setActivity(null); - } target.setTimestamp(injectCurrentTimeMillis()); if (replacingIcon) { @@ -2414,7 +2407,8 @@ public class ShortcutService extends IShortcutService.Stub { return false; } if (componentName != null) { - if (!Objects.equals(componentName, si.getActivity())) { + if (si.getActivity() != null + && !si.getActivity().equals(componentName)) { return false; } } @@ -3934,8 +3928,4 @@ public class ShortcutService extends IShortcutService.Stub { forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates)); } } - - void verifyError() { - Slog.e(TAG, "See logcat for errors"); - } } diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index a1060dcb6eff..6d06838cd24f 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -265,19 +265,6 @@ public class DexManager { public void mergeAppDataDirs(ApplicationInfo ai, int userId) { Set<String> dataDirs = putIfAbsent(mAppDataDirs, userId, new HashSet<>()); dataDirs.add(ai.dataDir); - - // Compute and cache the real path as well since data dir may be a symlink. - // e.g. /data/data/ -> /data/user/0/ - try { - dataDirs.add(PackageManagerServiceUtils.realpath(new File(ai.dataDir))); - } catch (IOException e) { - if (DEBUG) { - // Verify why we're getting spam at boot for some devices. - // b/33807524 - Slog.w(TAG, "Error to get realpath of " + ai.dataDir, e); - } - } - } public int searchDex(String dexPath, int userId) { @@ -302,6 +289,20 @@ public class DexManager { return DEX_SEARCH_FOUND_SECONDARY; } } + + // TODO(calin): What if we get a symlink? e.g. data dir may be a symlink, + // /data/data/ -> /data/user/0/. + if (DEBUG) { + try { + String dexPathReal = PackageManagerServiceUtils.realpath(new File(dexPath)); + if (dexPathReal != dexPath) { + Slog.d(TAG, "Dex loaded with symlink. dexPath=" + + dexPath + " dexPathReal=" + dexPathReal); + } + } catch (IOException e) { + // Ignore + } + } return DEX_SEARCH_NOT_FOUND; } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 349740b0bd38..dc06d129c5bb 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -166,6 +166,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { } /** + * Get an array with display ids ordered by focus priority - last items should be given + * focus first. Sparse array just maps position to displayId. + */ + void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) { + displaysInFocusOrder.clear(); + + final int size = mChildren.size(); + for (int i = 0; i < size; ++i) { + displaysInFocusOrder.put(i, mChildren.get(i).getDisplayId()); + } + } + + /** * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if * there is a Display for the displayId. * diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d5aa01b6a0b7..38cb54320a1b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -6638,6 +6638,16 @@ public class WindowManagerService extends IWindowManager.Stub displayInfo.overscanRight, displayInfo.overscanBottom); } + /** + * Get an array with display ids ordered by focus priority - last items should be given + * focus first. Sparse array just maps position to displayId. + */ + public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) { + synchronized(mWindowMap) { + mRoot.getDisplaysInFocusOrder(displaysInFocusOrder); + } + } + @Override public void setOverscan(int displayId, int left, int top, int right, int bottom) { if (mContext.checkCallingOrSelfPermission( diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index e5c8d02c4fd1..0346e4c04492 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4788,7 +4788,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private void wipeDataLocked(boolean wipeExtRequested, String reason, boolean force) { + private void wipeDataNoLock(boolean wipeExtRequested, String reason, boolean force) { + wtfIfInLock(); + if (wipeExtRequested) { StorageManager sm = (StorageManager) mContext.getSystemService( Context.STORAGE_SERVICE); @@ -4808,13 +4810,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } final int userHandle = mInjector.userHandleGetCallingUserId(); enforceFullCrossUsersPermission(userHandle); + + final String source; synchronized (this) { // This API can only be called by an active device admin, // so try to retrieve it to check that the caller is one. final ActiveAdmin admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WIPE_DATA); - - final String source = admin.info.getComponent().flattenToShortString(); + source = admin.info.getComponent().flattenToShortString(); long ident = mInjector.binderClearCallingIdentity(); try { @@ -4844,45 +4847,47 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0; - wipeDeviceOrUserLocked(wipeExtRequested, userHandle, - "DevicePolicyManager.wipeData() from " + source, /*force=*/ true); } finally { mInjector.binderRestoreCallingIdentity(ident); } } + final boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0; + wipeDeviceNoLock(wipeExtRequested, userHandle, + "DevicePolicyManager.wipeData() from " + source, /*force=*/ true); } - private void wipeDeviceOrUserLocked( + private void wipeDeviceNoLock( boolean wipeExtRequested, final int userHandle, String reason, boolean force) { - // TODO If split user is enabled and the device owner is set in the primary user (rather - // than system), we should probably trigger factory reset. Current code just remove - // that user (but still clears FRP...) - if (userHandle == UserHandle.USER_SYSTEM) { - wipeDataLocked(wipeExtRequested, reason, force); - } else { - mHandler.post(new Runnable() { - @Override - public void run() { - try { - IActivityManager am = mInjector.getIActivityManager(); - if (am.getCurrentUser().id == userHandle) { - am.switchUser(UserHandle.USER_SYSTEM); - } + wtfIfInLock(); - boolean userRemoved = force - ? mUserManagerInternal.removeUserEvenWhenDisallowed(userHandle) - : mUserManager.removeUser(userHandle); - if (!userRemoved) { - Slog.w(LOG_TAG, "Couldn't remove user " + userHandle); - } else if (isManagedProfile(userHandle)) { - sendWipeProfileNotification(); - } - } catch (RemoteException re) { - // Shouldn't happen + long ident = mInjector.binderClearCallingIdentity(); + try { + // TODO If split user is enabled and the device owner is set in the primary user (rather + // than system), we should probably trigger factory reset. Current code just remove + // that user (but still clears FRP...) + if (userHandle == UserHandle.USER_SYSTEM) { + wipeDataNoLock(wipeExtRequested, reason, force); + } else { + try { + IActivityManager am = mInjector.getIActivityManager(); + if (am.getCurrentUser().id == userHandle) { + am.switchUser(UserHandle.USER_SYSTEM); + } + + boolean userRemoved = force + ? mUserManagerInternal.removeUserEvenWhenDisallowed(userHandle) + : mUserManager.removeUser(userHandle); + if (!userRemoved) { + Slog.w(LOG_TAG, "Couldn't remove user " + userHandle); + } else if (isManagedProfile(userHandle)) { + sendWipeProfileNotification(); } + } catch (RemoteException re) { + // Shouldn't happen } - }); + } + } finally { + mInjector.binderRestoreCallingIdentity(ident); } } @@ -5047,8 +5052,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } if (wipeData) { // Call without holding lock. - wipeDeviceOrUserLocked(false, identifier, - "reportFailedPasswordAttempt()", false); + wipeDeviceNoLock(false, identifier, "reportFailedPasswordAttempt()", false); } } finally { mInjector.binderRestoreCallingIdentity(ident); @@ -6550,6 +6554,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } /** + * Calls wtfStack() if called with the DPMS lock held. + */ + private void wtfIfInLock() { + if (Thread.holdsLock(this)) { + Slog.wtfStack(LOG_TAG, "Shouldn't be called with DPMS lock held"); + } + } + + /** * The profile owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS * permission. * The profile owner can only be set before the user setup phase has completed, @@ -9870,10 +9883,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!isAdb()) { return true; } - if (Thread.holdsLock(this)) { - Slog.wtf(LOG_TAG, "hasIncompatibleAccountsNoLock() called with the DPMS lock held."); - return true; - } + wtfIfInLock(); final long token = mInjector.binderClearCallingIdentity(); try { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 5b46f5144fd5..f4b423010855 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -165,6 +165,8 @@ public final class SystemServer { "com.android.server.LockSettingsService$Lifecycle"; private static final String STORAGE_MANAGER_SERVICE_CLASS = "com.android.server.StorageManagerService$Lifecycle"; + private static final String STORAGE_STATS_SERVICE_CLASS = + "com.android.server.usage.StorageStatsService$Lifecycle"; private static final String SEARCH_MANAGER_SERVICE_CLASS = "com.android.server.search.SearchManagerService$Lifecycle"; private static final String THERMAL_OBSERVER_CLASS = @@ -795,7 +797,7 @@ public final class SystemServer { if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { if (!disableStorage && - !"0".equals(SystemProperties.get("system_init.startmountservice"))) { + !"0".equals(SystemProperties.get("system_init.startmountservice"))) { traceBeginAndSlog("StartStorageManagerService"); try { /* @@ -806,7 +808,15 @@ public final class SystemServer { storageManager = IStorageManager.Stub.asInterface( ServiceManager.getService("mount")); } catch (Throwable e) { - reportWtf("starting StorageManager Service", e); + reportWtf("starting StorageManagerService", e); + } + traceEnd(); + + traceBeginAndSlog("StartStorageStatsService"); + try { + mSystemServiceManager.startService(STORAGE_STATS_SERVICE_CLASS); + } catch (Throwable e) { + reportWtf("starting StorageStatsService", e); } traceEnd(); } diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java index e1c0166ee39b..ef61ec242a4c 100644 --- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -126,7 +126,7 @@ public class NotificationManagerServiceTest { NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); - channel.setAllowed(false); + channel.setImportance(NotificationManager.IMPORTANCE_NONE); NotificationRecord r = generateNotificationRecord(channel); NotificationManagerService.EnqueueNotificationRunnable enqueue = mNotificationManagerService.new EnqueueNotificationRunnable(UserHandle.USER_SYSTEM, diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java index eb1021d9b6f3..f8061f6feb00 100644 --- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java @@ -488,25 +488,6 @@ public class RankingHelperTest { } @Test - public void testUpdate_userLockedAllowed() throws Exception { - final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); - channel.setAllowed(true); - channel.lockFields(NotificationChannel.USER_LOCKED_ALLOWED); - - mHelper.createNotificationChannel(pkg, uid, channel, false); - - final NotificationChannel channel2 = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); - channel2.setAllowed(false); - - mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2); - - // no fields should be changed - assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId())); - } - - @Test public void testUpdate_userLockedBadge() throws Exception { final NotificationChannel channel = new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); @@ -567,7 +548,6 @@ public class RankingHelperTest { channel.setBypassDnd(true); channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); channel.setShowBadge(true); - channel.setAllowed(false); int lockMask = 0; for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; @@ -595,7 +575,6 @@ public class RankingHelperTest { channel.setBypassDnd(true); channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); channel.setShowBadge(true); - channel.setAllowed(false); int lockMask = 0; for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index ae5da78bbab5..f934d347080f 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -50,10 +50,7 @@ LOCAL_JNI_SHARED_LIBRARIES := libservicestestsjni \ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk -# Code coverage puts us over the dex limit, so enable multi-dex for coverage-enabled builds -ifeq (true,$(EMMA_INSTRUMENT)) LOCAL_JACK_FLAGS := --multi-dex native -endif # EMMA_INSTRUMENT_STATIC LOCAL_STATIC_JAVA_LIBRARIES += ub-uiautomator diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index 9a9f81e03dfd..9c5c67237fd2 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -147,11 +147,11 @@ public class NetworkScoreServiceTest { @Test public void testRequestScores_noPermission() throws Exception { doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED), + .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mNetworkScoreService.requestScores(null); - fail("BROADCAST_NETWORK_PRIVILEGED not enforced."); + fail("REQUEST_NETWORK_SCORES not enforced."); } catch (SecurityException e) { // expected } @@ -184,11 +184,11 @@ public class NetworkScoreServiceTest { @Test public void testRequestRecommendation_noPermission() throws Exception { doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED), + .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mNetworkScoreService.requestRecommendation(mRecommendationRequest); - fail("BROADCAST_NETWORK_PRIVILEGED not enforced."); + fail("REQUEST_NETWORK_SCORES not enforced."); } catch (SecurityException e) { // expected } @@ -324,7 +324,7 @@ public class NetworkScoreServiceTest { @Test public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() { when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); - when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) .thenReturn(PackageManager.PERMISSION_DENIED); try { mNetworkScoreService.clearScores(); @@ -337,7 +337,7 @@ public class NetworkScoreServiceTest { @Test public void testClearScores_activeScorer_noBroadcastNetworkPermission() { when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); - when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) .thenReturn(PackageManager.PERMISSION_DENIED); mNetworkScoreService.clearScores(); @@ -358,7 +358,7 @@ public class NetworkScoreServiceTest { public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission() throws RemoteException { when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); - when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) .thenReturn(PackageManager.PERMISSION_GRANTED); mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache, @@ -384,7 +384,7 @@ public class NetworkScoreServiceTest { @Test public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() { when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); - when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) .thenReturn(PackageManager.PERMISSION_DENIED); try { @@ -398,7 +398,7 @@ public class NetworkScoreServiceTest { @Test public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() { doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString()); + eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mNetworkScoreService.registerNetworkScoreCache( @@ -412,7 +412,7 @@ public class NetworkScoreServiceTest { @Test public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() { doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( - eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString()); + eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mNetworkScoreService.unregisterNetworkScoreCache( diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index dcaab76b1f53..10ca90207d85 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -404,7 +404,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { @Override boolean injectIsActivityEnabledAndExported(ComponentName activity, @UserIdInt int userId) { - assertNotNull(activity); return mEnabledActivityChecker.test(activity, userId); } @@ -450,11 +449,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { // During tests, WTF is fatal. fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th)); } - - @Override - void verifyError() { - fail("Verify error"); - } } /** ShortcutManager with injection override methods. */ diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java index 97bcaf0a565a..74c1ca5015c8 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java @@ -1292,43 +1292,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { /* activity =*/ null, /* flags */ 0), getCallingUser()); }); - // Make sure floating shortcuts don't match with an activity. - // At this point, s1 is dynamic and pinned, so it still has a target activity. - runWithCaller(LAUNCHER_1, USER_0, () -> { - assertWith(mLauncherApps.getShortcuts(buildQuery( - /* time =*/ 0, - CALLING_PACKAGE_2, - /* activity =*/ new ComponentName(CALLING_PACKAGE_2, - ShortcutActivity2.class.getName()), - ShortcutQuery.FLAG_GET_PINNED), - getCallingUser())) - .haveIds("s3") - .areAllPinned() - .areAllDynamic() - .areAllWithActivity(new ComponentName(CALLING_PACKAGE_2, - ShortcutActivity2.class.getName())); - }); - - // Now remove as a dynamic, making it floating. - runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { - mManager.removeDynamicShortcuts(list("s3")); - assertWith(mManager.getPinnedShortcuts()) - .selectFloating() - .areAllWithNoActivity(); - }); - - runWithCaller(LAUNCHER_1, USER_0, () -> { - // This shouldn't match now. - assertWith(mLauncherApps.getShortcuts(buildQuery( - /* time =*/ 0, - CALLING_PACKAGE_2, - /* activity =*/ new ComponentName(CALLING_PACKAGE_2, - ShortcutActivity2.class.getName()), - ShortcutQuery.FLAG_GET_PINNED), - getCallingUser())) - .isEmpty(); - }); - + // TODO More tests: pinned but dynamic. } public void testGetShortcuts_shortcutKinds() throws Exception { diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index 7486858eeace..d25923c019ca 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -1052,7 +1052,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(CALLING_PACKAGE_1, si.getPackage()); assertEquals("id", si.getId()); - assertNull(si.getActivity()); // It's now floating, so no target activity. + assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName()); assertEquals(null, si.getIcon()); assertEquals("title", si.getTitle()); assertEquals("text", si.getText()); @@ -1116,7 +1116,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(CALLING_PACKAGE_1, si.getPackage()); assertEquals("id", si.getId()); - assertNull(si.getActivity()); // It's now floating, so no target activity. + assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName()); assertEquals(null, si.getIcon()); assertEquals(10, si.getTitleResId()); assertEquals("r10", si.getTitleResName()); diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java new file mode 100644 index 000000000000..cb9cb1219a0b --- /dev/null +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017 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.server.usage; + +import android.app.AppOpsManager; +import android.app.usage.IStorageStatsManager; +import android.app.usage.StorageStats; +import android.app.usage.StorageSummary; +import android.content.Context; +import android.os.Binder; +import android.os.UserHandle; +import android.os.storage.StorageManager; + +import com.android.server.SystemService; +import com.android.server.pm.Installer; + +public class StorageStatsService extends IStorageStatsManager.Stub { + private static final String TAG = "StorageStatsService"; + + public static class Lifecycle extends SystemService { + private StorageStatsService mService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mService = new StorageStatsService(getContext()); + publishBinderService(Context.STORAGE_STATS_SERVICE, mService); + } + } + + private final Context mContext; + private final AppOpsManager mAppOps; + private final StorageManager mStorage; + private final Installer mInstaller; + + public StorageStatsService(Context context) { + mContext = context; + mAppOps = context.getSystemService(AppOpsManager.class); + mStorage = context.getSystemService(StorageManager.class); + mInstaller = new Installer(context); + } + + private void enforcePermission(int callingUid, String callingPackage) { + final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, + callingUid, callingPackage); + switch (mode) { + case AppOpsManager.MODE_ALLOWED: + return; + case AppOpsManager.MODE_DEFAULT: + mContext.enforceCallingPermission( + android.Manifest.permission.PACKAGE_USAGE_STATS, TAG); + default: + throw new SecurityException("Blocked by mode " + mode); + } + } + + @Override + public StorageStats queryStats(String volumeUuid, int uid, String callingPackage) { + enforcePermission(Binder.getCallingUid(), callingPackage); + if (UserHandle.getUserId(uid) != UserHandle.getCallingUserId()) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); + } + + // TODO: call installd to collect quota stats + return null; + } + + @Override + public StorageSummary querySummary(String volumeUuid, String callingPackage) { + enforcePermission(Binder.getCallingUid(), callingPackage); + + // TODO: call installd to collect quota stats + return null; + } +} diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index 2ae46540674f..9d9d71f66de9 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -62,7 +62,7 @@ public final class Bitmap_Delegate { public enum BitmapCreateFlags { - PREMULTIPLIED, MUTABLE + NONE, PREMULTIPLIED, MUTABLE } // ---- delegate manager ---- @@ -616,6 +616,26 @@ public final class Bitmap_Delegate { // do nothing as Bitmap_Delegate does not have caches } + @LayoutlibDelegate + /*package*/ static Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap) { + Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(nativeBitmap); + if (srcBmpDelegate == null) { + return null; + } + + BufferedImage srcImage = srcBmpDelegate.getImage(); + + // create the image + BufferedImage image = new BufferedImage(srcImage.getColorModel(), srcImage.copyData(null), + srcImage.isAlphaPremultiplied(), null); + + // create a delegate with the content of the stream. + Bitmap_Delegate delegate = new Bitmap_Delegate(image, srcBmpDelegate.getConfig()); + + return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.NONE), + Bitmap.getDefaultDensity()); + } + // ---- Private delegate/helper methods ---- private Bitmap_Delegate(BufferedImage image, Config config) { diff --git a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java deleted file mode 100644 index 10cc57294644..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2010 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.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.LayerRasterizer - * - * Through the layoutlib_create tool, the original native methods of LayerRasterizer have - * been replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original LayerRasterizer class. - * - * Because this extends {@link Rasterizer_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link Rasterizer_Delegate}. - * - * @see Rasterizer_Delegate - * - */ -public class LayerRasterizer_Delegate extends Rasterizer_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Layer Rasterizers are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeConstructor() { - LayerRasterizer_Delegate newDelegate = new LayerRasterizer_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void nativeAddLayer(long native_layer, long native_paint, float dx, float dy) { - - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index e68d8b3e9f93..9b8fa996a017 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -99,7 +99,6 @@ public class Paint_Delegate { private Shader_Delegate mShader; private PathEffect_Delegate mPathEffect; private MaskFilter_Delegate mMaskFilter; - private Rasterizer_Delegate mRasterizer; private Locale mLocale = Locale.getDefault(); @@ -248,15 +247,6 @@ public class Paint_Delegate { return mMaskFilter; } - /** - * Returns the {@link Rasterizer} delegate or null if none have been set - * - * @return the delegate or null. - */ - public Rasterizer_Delegate getRasterizer() { - return mRasterizer; - } - // ---- native methods ---- @LayoutlibDelegate @@ -898,25 +888,6 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long nSetRasterizer(long native_object, long rasterizer) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return rasterizer; - } - - delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer); - - // since none of those are supported, display a fidelity warning right away - if (delegate.mRasterizer != null && !delegate.mRasterizer.isSupported()) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER, - delegate.mRasterizer.getSupportMessage(), null, null /*data*/); - } - - return rasterizer; - } - - @LayoutlibDelegate /*package*/ static int nGetTextAlign(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); @@ -1235,7 +1206,6 @@ public class Paint_Delegate { mShader = paint.mShader; mPathEffect = paint.mPathEffect; mMaskFilter = paint.mMaskFilter; - mRasterizer = paint.mRasterizer; mHintingMode = paint.mHintingMode; if (needsFontUpdate) { @@ -1262,7 +1232,6 @@ public class Paint_Delegate { mShader = null; mPathEffect = null; mMaskFilter = null; - mRasterizer = null; updateFontObject(); mHintingMode = Paint.HINTING_ON; } diff --git a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java index fc9b4f772883..7f707c9aa01a 100644 --- a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java @@ -56,8 +56,8 @@ public final class PathMeasure_Delegate { if (native_path != 0) { if (forceClosed) { // Copy the path and call close - native_path = Path_Delegate.init2(native_path); - Path_Delegate.native_close(native_path); + native_path = Path_Delegate.nInit(native_path); + Path_Delegate.nClose(native_path); } Path_Delegate pathDelegate = Path_Delegate.getDelegate(native_path); @@ -108,8 +108,8 @@ public final class PathMeasure_Delegate { if (native_path != 0) { if (forceClosed) { // Copy the path and call close - native_path = Path_Delegate.init2(native_path); - Path_Delegate.native_close(native_path); + native_path = Path_Delegate.nInit(native_path); + Path_Delegate.nClose(native_path); } Path_Delegate pathDelegate = Path_Delegate.getDelegate(native_path); @@ -184,28 +184,28 @@ public final class PathMeasure_Delegate { if (type != PathIterator.SEG_MOVETO) { float[] lastPoint = new float[2]; iterator.getCurrentSegmentEnd(lastPoint); - Path_Delegate.native_moveTo(native_dst_path, lastPoint[0], lastPoint[1]); + Path_Delegate.nMoveTo(native_dst_path, lastPoint[0], lastPoint[1]); } } isZeroLength = isZeroLength && iterator.getCurrentSegmentLength() > 0; switch (type) { case PathIterator.SEG_MOVETO: - Path_Delegate.native_moveTo(native_dst_path, points[0], points[1]); + Path_Delegate.nMoveTo(native_dst_path, points[0], points[1]); break; case PathIterator.SEG_LINETO: - Path_Delegate.native_lineTo(native_dst_path, points[0], points[1]); + Path_Delegate.nLineTo(native_dst_path, points[0], points[1]); break; case PathIterator.SEG_CLOSE: - Path_Delegate.native_close(native_dst_path); + Path_Delegate.nClose(native_dst_path); break; case PathIterator.SEG_CUBICTO: - Path_Delegate.native_cubicTo(native_dst_path, points[0], points[1], + Path_Delegate.nCubicTo(native_dst_path, points[0], points[1], points[2], points[3], points[4], points[5]); break; case PathIterator.SEG_QUADTO: - Path_Delegate.native_quadTo(native_dst_path, points[0], points[1], + Path_Delegate.nQuadTo(native_dst_path, points[0], points[1], points[2], points[3]); break; diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java index 219c487cac53..579fce09d094 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java @@ -98,7 +98,7 @@ public final class Path_Delegate { // ---- native methods ---- @LayoutlibDelegate - /*package*/ static long init1() { + /*package*/ static long nInit() { // create the delegate Path_Delegate newDelegate = new Path_Delegate(); @@ -106,7 +106,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static long init2(long nPath) { + /*package*/ static long nInit(long nPath) { // create the delegate Path_Delegate newDelegate = new Path_Delegate(); @@ -120,7 +120,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_reset(long nPath) { + /*package*/ static void nReset(long nPath) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -130,20 +130,20 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_rewind(long nPath) { + /*package*/ static void nRewind(long nPath) { // call out to reset since there's nothing to optimize in // terms of data structs. - native_reset(nPath); + nReset(nPath); } @LayoutlibDelegate - /*package*/ static void native_set(long native_dst, long native_src) { + /*package*/ static void nSet(long native_dst, long nSrc) { Path_Delegate pathDstDelegate = sManager.getDelegate(native_dst); if (pathDstDelegate == null) { return; } - Path_Delegate pathSrcDelegate = sManager.getDelegate(native_src); + Path_Delegate pathSrcDelegate = sManager.getDelegate(nSrc); if (pathSrcDelegate == null) { return; } @@ -152,14 +152,14 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static boolean native_isConvex(long nPath) { + /*package*/ static boolean nIsConvex(long nPath) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "Path.isConvex is not supported.", null, null); return true; } @LayoutlibDelegate - /*package*/ static int native_getFillType(long nPath) { + /*package*/ static int nGetFillType(long nPath) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return 0; @@ -169,7 +169,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - public static void native_setFillType(long nPath, int ft) { + public static void nSetFillType(long nPath, int ft) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -179,14 +179,14 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static boolean native_isEmpty(long nPath) { + /*package*/ static boolean nIsEmpty(long nPath) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); return pathDelegate == null || pathDelegate.isEmpty(); } @LayoutlibDelegate - /*package*/ static boolean native_isRect(long nPath, RectF rect) { + /*package*/ static boolean nIsRect(long nPath, RectF rect) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return false; @@ -206,7 +206,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_computeBounds(long nPath, RectF bounds) { + /*package*/ static void nComputeBounds(long nPath, RectF bounds) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -216,13 +216,13 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_incReserve(long nPath, int extraPtCount) { + /*package*/ static void nIncReserve(long nPath, int extraPtCount) { // since we use a java2D path, there's no way to pre-allocate new points, // so we do nothing. } @LayoutlibDelegate - /*package*/ static void native_moveTo(long nPath, float x, float y) { + /*package*/ static void nMoveTo(long nPath, float x, float y) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -232,7 +232,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_rMoveTo(long nPath, float dx, float dy) { + /*package*/ static void nRMoveTo(long nPath, float dx, float dy) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -242,7 +242,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_lineTo(long nPath, float x, float y) { + /*package*/ static void nLineTo(long nPath, float x, float y) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -252,7 +252,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_rLineTo(long nPath, float dx, float dy) { + /*package*/ static void nRLineTo(long nPath, float dx, float dy) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -262,7 +262,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_quadTo(long nPath, float x1, float y1, float x2, float y2) { + /*package*/ static void nQuadTo(long nPath, float x1, float y1, float x2, float y2) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -272,7 +272,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_rQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2) { + /*package*/ static void nRQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -282,7 +282,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_cubicTo(long nPath, float x1, float y1, + /*package*/ static void nCubicTo(long nPath, float x1, float y1, float x2, float y2, float x3, float y3) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { @@ -293,7 +293,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_rCubicTo(long nPath, float x1, float y1, + /*package*/ static void nRCubicTo(long nPath, float x1, float y1, float x2, float y2, float x3, float y3) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { @@ -304,7 +304,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_arcTo(long nPath, float left, float top, float right, + /*package*/ static void nArcTo(long nPath, float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); @@ -316,7 +316,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_close(long nPath) { + /*package*/ static void nClose(long nPath) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -326,7 +326,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addRect(long nPath, + /*package*/ static void nAddRect(long nPath, float left, float top, float right, float bottom, int dir) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { @@ -337,7 +337,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addOval(long nPath, float left, float top, float right, + /*package*/ static void nAddOval(long nPath, float left, float top, float right, float bottom, int dir) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { @@ -349,7 +349,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addCircle(long nPath, float x, float y, float radius, int dir) { + /*package*/ static void nAddCircle(long nPath, float x, float y, float radius, int dir) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -361,7 +361,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addArc(long nPath, float left, float top, float right, + /*package*/ static void nAddArc(long nPath, float left, float top, float right, float bottom, float startAngle, float sweepAngle) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { @@ -375,7 +375,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addRoundRect(long nPath, float left, float top, float right, + /*package*/ static void nAddRoundRect(long nPath, float left, float top, float right, float bottom, float rx, float ry, int dir) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); @@ -388,7 +388,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addRoundRect(long nPath, float left, float top, float right, + /*package*/ static void nAddRoundRect(long nPath, float left, float top, float right, float bottom, float[] radii, int dir) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); @@ -405,17 +405,17 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addPath(long nPath, long src, float dx, float dy) { + /*package*/ static void nAddPath(long nPath, long src, float dx, float dy) { addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy)); } @LayoutlibDelegate - /*package*/ static void native_addPath(long nPath, long src) { + /*package*/ static void nAddPath(long nPath, long src) { addPath(nPath, src, null /*transform*/); } @LayoutlibDelegate - /*package*/ static void native_addPath(long nPath, long src, long matrix) { + /*package*/ static void nAddPath(long nPath, long src, long matrix) { Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); if (matrixDelegate == null) { return; @@ -425,7 +425,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_offset(long nPath, float dx, float dy) { + /*package*/ static void nOffset(long nPath, float dx, float dy) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -435,7 +435,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setLastPoint(long nPath, float dx, float dy) { + /*package*/ static void nSetLastPoint(long nPath, float dx, float dy) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; @@ -446,7 +446,7 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_transform(long nPath, long matrix, + /*package*/ static void nTransform(long nPath, long matrix, long dst_path) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { @@ -465,23 +465,23 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_transform(long nPath, long matrix) { - native_transform(nPath, matrix, 0); + /*package*/ static void nTransform(long nPath, long matrix) { + nTransform(nPath, matrix, 0); } @LayoutlibDelegate - /*package*/ static boolean native_op(long nPath1, long nPath2, int op, long result) { + /*package*/ static boolean nOp(long nPath1, long nPath2, int op, long result) { Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.op() not supported", null); return false; } @LayoutlibDelegate - /*package*/ static void finalizer(long nPath) { + /*package*/ static void nFinalize(long nPath) { sManager.removeJavaReferenceFor(nPath); } @LayoutlibDelegate - /*package*/ static float[] native_approximate(long nPath, float error) { + /*package*/ static float[] nApproximate(long nPath, float error) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return null; diff --git a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java deleted file mode 100644 index a742840c9183..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 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.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.Rasterizer - * - * Through the layoutlib_create tool, the original native methods of Rasterizer have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Rasterizer class. - * - * This also serve as a base class for all Rasterizer delegate classes. - * - * @see DelegateManager - * - */ -public abstract class Rasterizer_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<Rasterizer_Delegate> sManager = - new DelegateManager<Rasterizer_Delegate>(Rasterizer_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static Rasterizer_Delegate getDelegate(long nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void finalizer(long native_instance) { - sManager.removeJavaReferenceFor(native_instance); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java index cee679a1d469..430607aa178b 100644 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java @@ -1197,7 +1197,7 @@ public class VectorDrawable_Delegate { assert fillPaintDelegate != null; fillPaintDelegate.setColorFilter(filterPtr); fillPaintDelegate.setShader(fullPath.mFillGradient); - Path_Delegate.native_setFillType(mRenderPath.mNativePath, fullPath.mFillType); + Path_Delegate.nSetFillType(mRenderPath.mNativePath, fullPath.mFillType); BaseCanvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, fillPaint .getNativeInstance()); } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index a23bad6ed480..92fd75cc5a36 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -263,7 +263,6 @@ public final class CreateInfo implements ICreateInfo { "android.graphics.DrawFilter", "android.graphics.EmbossMaskFilter", "android.graphics.FontFamily", - "android.graphics.LayerRasterizer", "android.graphics.LightingColorFilter", "android.graphics.LinearGradient", "android.graphics.MaskFilter", @@ -277,7 +276,6 @@ public final class CreateInfo implements ICreateInfo { "android.graphics.PathMeasure", "android.graphics.PorterDuffColorFilter", "android.graphics.RadialGradient", - "android.graphics.Rasterizer", "android.graphics.Region", "android.graphics.Shader", "android.graphics.SumPathEffect", diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 9e897bff1122..18c124503136 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -59,7 +59,7 @@ interface IWifiManager int addOrUpdateNetwork(in WifiConfiguration config); - boolean addPasspointConfiguration(in PasspointConfiguration config); + boolean addOrUpdatePasspointConfiguration(in PasspointConfiguration config); boolean removePasspointConfiguration(in String fqdn); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 674c16156cc8..618a7192a612 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -842,31 +842,31 @@ public class WifiManager { } /** - * Add a Passpoint configuration. The configuration provides a credential + * Add or update a Passpoint configuration. The configuration provides a credential * for connecting to Passpoint networks that are operated by the Passpoint * service provider specified in the configuration. * * Each configuration is uniquely identified by its FQDN (Fully Qualified Domain - * Name). In the case when there is an existing configuration with the same base - * domain, the new configuration will replace the existing configuration. + * Name). In the case when there is an existing configuration with the same + * FQDN, the new configuration will replace the existing configuration. * * @param config The Passpoint configuration to be added - * @return true on success or false on failure + * @return true on success * @hide */ - public boolean addPasspointConfiguration(PasspointConfiguration config) { + public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) { try { - return mService.addPasspointConfiguration(config); + return mService.addOrUpdatePasspointConfiguration(config); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Remove a Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). + * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). * * @param fqdn The FQDN of the passpoint configuration to be removed - * @return true on success or false on failure + * @return true on success * @hide */ public boolean removePasspointConfiguration(String fqdn) { @@ -880,7 +880,9 @@ public class WifiManager { /** * Return the list of installed Passpoint configurations. * - * @return A list of PasspointConfiguration or null + * An empty list will be returned when no configurations are installed. + * + * @return A list of {@link PasspointConfiguration} * @hide */ public List<PasspointConfiguration> getPasspointConfigurations() { diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java b/wifi/java/android/net/wifi/aware/AttachCallback.java index 1e8dbd945b6e..90216f3f71d3 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java +++ b/wifi/java/android/net/wifi/aware/AttachCallback.java @@ -18,16 +18,16 @@ package android.net.wifi.aware; /** * Base class for Aware attach callbacks. Should be extended by applications and set when calling - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}. These are callbacks + * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}. These are callbacks * applying to the Aware connection as a whole - not to specific publish or subscribe sessions - - * for that see {@link WifiAwareDiscoverySessionCallback}. + * for that see {@link DiscoverySessionCallback}. * * @hide PROPOSED_AWARE_API */ -public class WifiAwareAttachCallback { +public class AttachCallback { /** * Called when Aware attach operation - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)} + * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)} * is completed and that we can now start discovery sessions or connections. * * @param session The Aware object on which we can execute further Aware operations - e.g. @@ -39,7 +39,7 @@ public class WifiAwareAttachCallback { /** * Called when Aware attach operation - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)} failed. + * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)} failed. */ public void onAttachFailed() { /* empty */ diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl b/wifi/java/android/net/wifi/aware/Characteristics.aidl index a35e71dada09..77305e9dae0a 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl +++ b/wifi/java/android/net/wifi/aware/Characteristics.aidl @@ -16,4 +16,4 @@ package android.net.wifi.aware; -parcelable WifiAwareCharacteristics; +parcelable Characteristics; diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java b/wifi/java/android/net/wifi/aware/Characteristics.java index 092aa341c9b3..1c3e39025439 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java +++ b/wifi/java/android/net/wifi/aware/Characteristics.java @@ -25,7 +25,7 @@ import android.os.Parcelable; * * @hide PROPOSED_AWARE_API */ -public class WifiAwareCharacteristics implements Parcelable { +public class Characteristics implements Parcelable { /** @hide */ public static final String KEY_MAX_SERVICE_NAME_LENGTH = "key_max_service_name_length"; /** @hide */ @@ -37,7 +37,7 @@ public class WifiAwareCharacteristics implements Parcelable { private Bundle mCharacteristics = new Bundle(); /** @hide : should not be created by apps */ - public WifiAwareCharacteristics(Bundle characteristics) { + public Characteristics(Bundle characteristics) { mCharacteristics = characteristics; } @@ -58,7 +58,7 @@ public class WifiAwareCharacteristics implements Parcelable { * message exchange. Restricts the parameters of the * {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])}, * {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}, and - * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])} + * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} * variants. * * @return A positive integer, maximum length of byte array for Aware messaging. @@ -89,17 +89,17 @@ public class WifiAwareCharacteristics implements Parcelable { return 0; } - public static final Creator<WifiAwareCharacteristics> CREATOR = - new Creator<WifiAwareCharacteristics>() { + public static final Creator<Characteristics> CREATOR = + new Creator<Characteristics>() { @Override - public WifiAwareCharacteristics createFromParcel(Parcel in) { - WifiAwareCharacteristics c = new WifiAwareCharacteristics(in.readBundle()); + public Characteristics createFromParcel(Parcel in) { + Characteristics c = new Characteristics(in.readBundle()); return c; } @Override - public WifiAwareCharacteristics[] newArray(int size) { - return new WifiAwareCharacteristics[size]; + public Characteristics[] newArray(int size) { + return new Characteristics[size]; } }; } diff --git a/wifi/java/android/net/wifi/aware/ConfigRequest.java b/wifi/java/android/net/wifi/aware/ConfigRequest.java index 4b21b15d4994..6a5957badafb 100644 --- a/wifi/java/android/net/wifi/aware/ConfigRequest.java +++ b/wifi/java/android/net/wifi/aware/ConfigRequest.java @@ -22,7 +22,7 @@ import android.os.Parcelable; /** * Defines a request object to configure a Wi-Fi Aware network. Built using * {@link ConfigRequest.Builder}. Configuration is requested using - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}. + * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}. * Note that the actual achieved configuration may be different from the * requested configuration - since different applications may request different * configurations. diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java index 2812ad4f147d..c89718f8b132 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java @@ -29,21 +29,21 @@ import java.lang.ref.WeakReference; /** * A class representing a single publish or subscribe Aware session. This object * will not be created directly - only its child classes are available: - * {@link WifiAwarePublishDiscoverySession} and {@link WifiAwareSubscribeDiscoverySession}. This + * {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This * class provides functionality common to both publish and subscribe discovery sessions: * <ul> - * <li>Sending messages: {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[])} or - * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)} methods. + * <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} or + * {@link #sendMessage(PeerHandle, int, byte[], int)} methods. * <li>Creating a network-specifier when requesting a Aware connection: - * {@link #createNetworkSpecifier(WifiAwareManager.PeerHandle, byte[])}. + * {@link #createNetworkSpecifier(PeerHandle, byte[])}. * </ul> * The {@link #destroy()} method must be called to destroy discovery sessions once they are * no longer needed. * * @hide PROPOSED_AWARE_API */ -public class WifiAwareDiscoveryBaseSession { - private static final String TAG = "WifiAwareDiscBaseSsn"; +public class DiscoverySession { + private static final String TAG = "DiscoverySession"; private static final boolean DBG = false; private static final boolean VDBG = false; // STOPSHIP if true @@ -62,7 +62,7 @@ public class WifiAwareDiscoveryBaseSession { /** * Return the maximum permitted retry count when sending messages using - * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}. + * {@link #sendMessage(PeerHandle, int, byte[], int)}. * * @return Maximum retry count when sending messages. */ @@ -71,7 +71,7 @@ public class WifiAwareDiscoveryBaseSession { } /** @hide */ - public WifiAwareDiscoveryBaseSession(WifiAwareManager manager, int clientId, int sessionId) { + public DiscoverySession(WifiAwareManager manager, int clientId, int sessionId) { if (VDBG) { Log.v(TAG, "New discovery session created: manager=" + manager + ", clientId=" + clientId + ", sessionId=" + sessionId); @@ -93,7 +93,7 @@ public class WifiAwareDiscoveryBaseSession { * This operation must be done on a session which is no longer needed. Otherwise system * resources will continue to be utilized until the application exits. The only * exception is a session for which we received a termination callback, - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}. + * {@link DiscoverySessionCallback#onSessionTerminated()}. */ public void destroy() { WifiAwareManager mgr = mMgr.get(); @@ -139,23 +139,23 @@ public class WifiAwareDiscoveryBaseSession { /** * Sends a message to the specified destination. Aware messages are transmitted in the context * of a discovery session - executed subsequent to a publish/subscribe - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} event. * <p> * Aware messages are not guaranteed delivery. Callbacks on - * {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully, - * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission + * {@link DiscoverySessionCallback} indicate message was transmitted successfully, + * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission * failed (possibly after several retries) - - * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}. + * {@link DiscoverySessionCallback#onMessageSendFailed(int)}. * <p> * The peer will get a callback indicating a message was received using - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])}. * * @param peerHandle The peer's handle for the message. Must be a result of an - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} or - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])} events. * @param messageId An arbitrary integer used by the caller to identify the message. The same * integer ID will be returned in the callbacks indicating message send success or @@ -167,7 +167,7 @@ public class WifiAwareDiscoveryBaseSession { * (note: no retransmissions are attempted in other failure cases). A value of 0 * indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}. */ - public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId, + public void sendMessage(@NonNull PeerHandle peerHandle, int messageId, @Nullable byte[] message, int retryCount) { if (mTerminated) { Log.w(TAG, "sendMessage: called on terminated session"); @@ -186,25 +186,25 @@ public class WifiAwareDiscoveryBaseSession { /** * Sends a message to the specified destination. Aware messages are transmitted in the context * of a discovery session - executed subsequent to a publish/subscribe - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} event. * <p> * Aware messages are not guaranteed delivery. Callbacks on - * {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully, - * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission + * {@link DiscoverySessionCallback} indicate message was transmitted successfully, + * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission * failed (possibly after several retries) - - * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}. + * {@link DiscoverySessionCallback#onMessageSendFailed(int)}. * <p> * The peer will get a callback indicating a message was received using - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])}. - * Equivalent to {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)} + * Equivalent to {@link #sendMessage(PeerHandle, int, byte[], int)} * with a {@code retryCount} of 0. * * @param peerHandle The peer's handle for the message. Must be a result of an - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} or - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])} events. * @param messageId An arbitrary integer used by the caller to identify the message. The same * integer ID will be returned in the callbacks indicating message send success or @@ -212,16 +212,16 @@ public class WifiAwareDiscoveryBaseSession { * can be arbitrary and non-unique. * @param message The message to be transmitted. */ - public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId, + public void sendMessage(@NonNull PeerHandle peerHandle, int messageId, @Nullable byte[] message) { sendMessage(peerHandle, messageId, message, 0); } /** * Start a ranging operation with the specified peers. The peer IDs are obtained from an - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} or - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])} operation - can * only range devices which are part of an ongoing discovery session. * @@ -265,9 +265,9 @@ public class WifiAwareDiscoveryBaseSession { * and a Publisher is a RESPONDER. * * @param peerHandle The peer's handle obtained through - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} or - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request * from only that peer. A RESPONDER may specified a null - indicating that * it will accept connection requests from any device. @@ -283,7 +283,7 @@ public class WifiAwareDiscoveryBaseSession { * android.net.ConnectivityManager.NetworkCallback)} * [or other varieties of that API]. */ - public String createNetworkSpecifier(@Nullable WifiAwareManager.PeerHandle peerHandle, + public String createNetworkSpecifier(@Nullable PeerHandle peerHandle, @Nullable byte[] token) { if (mTerminated) { Log.w(TAG, "createNetworkSpecifier: called on terminated session"); @@ -295,7 +295,7 @@ public class WifiAwareDiscoveryBaseSession { return null; } - int role = this instanceof WifiAwareSubscribeDiscoverySession + int role = this instanceof SubscribeDiscoverySession ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java index fdf0d013334d..1fe449fc1115 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java @@ -16,79 +16,53 @@ package android.net.wifi.aware; -import android.annotation.IntDef; import android.annotation.NonNull; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.List; /** * Base class for Aware session events callbacks. Should be extended by * applications wanting notifications. The callbacks are set when a * publish or subscribe session is created using - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} or - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * android.os.Handler)}. * <p> * A single callback is set at session creation - it cannot be replaced. * * @hide PROPOSED_AWARE_API */ -public class WifiAwareDiscoverySessionCallback { - /** @hide */ - @IntDef({ - TERMINATE_REASON_DONE, TERMINATE_REASON_FAIL }) - @Retention(RetentionPolicy.SOURCE) - public @interface SessionTerminateCodes { - } - - /** - * Indicates that publish or subscribe session is done - all the - * requested operations (per {@link PublishConfig} or - * {@link SubscribeConfig}) have been executed. Failure reason flag for - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback. - */ - public static final int TERMINATE_REASON_DONE = 100; - - /** - * Indicates that publish or subscribe session is terminated due to a - * failure. - * Failure reason flag for - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback. - */ - public static final int TERMINATE_REASON_FAIL = 101; - +public class DiscoverySessionCallback { /** * Called when a publish operation is started successfully in response to a - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} operation. * - * @param session The {@link WifiAwarePublishDiscoverySession} used to control the + * @param session The {@link PublishDiscoverySession} used to control the * discovery session. */ - public void onPublishStarted(@NonNull WifiAwarePublishDiscoverySession session) { + public void onPublishStarted(@NonNull PublishDiscoverySession session) { /* empty */ } /** * Called when a subscribe operation is started successfully in response to a - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * android.os.Handler)} operation. * - * @param session The {@link WifiAwareSubscribeDiscoverySession} used to control the + * @param session The {@link SubscribeDiscoverySession} used to control the * discovery session. */ - public void onSubscribeStarted(@NonNull WifiAwareSubscribeDiscoverySession session) { + public void onSubscribeStarted(@NonNull SubscribeDiscoverySession session) { /* empty */ } /** * Called when a publish or subscribe discovery session configuration update request * succeeds. Called in response to - * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * {@link PublishDiscoverySession#updatePublish(PublishConfig)} or + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. */ public void onSessionConfigUpdated() { /* empty */ @@ -96,12 +70,12 @@ public class WifiAwareDiscoverySessionCallback { /** * Called when a publish or subscribe discovery session cannot be created: - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} or - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * android.os.Handler)}, or when a configuration update fails: - * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * {@link PublishDiscoverySession#updatePublish(PublishConfig)} or + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. * <p> * For discovery session updates failure leaves the session running with its previous * configuration - the discovery session is not terminated. @@ -112,14 +86,11 @@ public class WifiAwareDiscoverySessionCallback { /** * Called when a discovery session (publish or subscribe) terminates. Termination may be due - * to user-request (either directly through {@link WifiAwareDiscoveryBaseSession#destroy()} or + * to user-request (either directly through {@link DiscoverySession#destroy()} or * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)} - * or {@link SubscribeConfig.Builder#setTtlSec(int)}) or due to a failure. - * - * @param reason The termination reason using - * {@code WifiAwareDiscoverySessionCallback.TERMINATE_*} codes. + * or {@link SubscribeConfig.Builder#setTtlSec(int)}). */ - public void onSessionTerminated(@SessionTerminateCodes int reason) { + public void onSessionTerminated() { /* empty */ } @@ -133,19 +104,19 @@ public class WifiAwareDiscoverySessionCallback { * configuration. * @param matchFilter The filter which resulted in this service discovery. */ - public void onServiceDiscovered(WifiAwareManager.PeerHandle peerHandle, + public void onServiceDiscovered(PeerHandle peerHandle, byte[] serviceSpecificInfo, List<byte[]> matchFilter) { /* empty */ } /** * Called in response to - * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])} + * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} * when a message is transmitted successfully - i.e. when it was received successfully by the * peer (corresponds to an ACK being received). * <p> * Note that either this callback or - * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)} will be + * {@link DiscoverySessionCallback#onMessageSendFailed(int)} will be * received - never both. * * @param messageId The arbitrary message ID specified when sending the message. @@ -157,11 +128,11 @@ public class WifiAwareDiscoverySessionCallback { /** * Called when message transmission fails - when no ACK is received from the peer. * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using - * the {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, + * the {@link DiscoverySession#sendMessage(PeerHandle, int, * byte[], int)} method) - this event is received after all retries are exhausted. * <p> * Note that either this callback or - * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)} will be received + * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)} will be received * - never both. * * @param messageId The arbitrary message ID specified when sending the message. @@ -172,14 +143,14 @@ public class WifiAwareDiscoverySessionCallback { /** * Called when a message is received from a discovery session peer - in response to the - * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, - * byte[])} or {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, + * peer's {@link DiscoverySession#sendMessage(PeerHandle, int, + * byte[])} or {@link DiscoverySession#sendMessage(PeerHandle, * int, byte[], int)}. * * @param peerHandle An opaque handle to the peer matching our discovery operation. * @param message A byte array containing the message. */ - public void onMessageReceived(WifiAwareManager.PeerHandle peerHandle, byte[] message) { + public void onMessageReceived(PeerHandle peerHandle, byte[] message) { /* empty */ } } diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl index 9c92807c63b5..794c142775f3 100644 --- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl +++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl @@ -23,7 +23,7 @@ import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; import android.net.wifi.aware.IWifiAwareEventCallback; import android.net.wifi.aware.PublishConfig; import android.net.wifi.aware.SubscribeConfig; -import android.net.wifi.aware.WifiAwareCharacteristics; +import android.net.wifi.aware.Characteristics; import android.net.wifi.RttManager; /** @@ -37,7 +37,7 @@ interface IWifiAwareManager void enableUsage(); void disableUsage(); boolean isUsageEnabled(); - WifiAwareCharacteristics getCharacteristics(); + Characteristics getCharacteristics(); // client API void connect(in IBinder binder, in String callingPackage, in IWifiAwareEventCallback callback, diff --git a/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java index e8f52cd4bdeb..b0f97bda0339 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java +++ b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java @@ -28,7 +28,7 @@ package android.net.wifi.aware; * * @hide PROPOSED_AWARE_API */ -public class WifiAwareIdentityChangedListener { +public class IdentityChangedListener { /** * @param mac The MAC address of the Aware discovery interface. The application must have the * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to get the actual MAC address, diff --git a/wifi/java/android/net/wifi/aware/PeerHandle.java b/wifi/java/android/net/wifi/aware/PeerHandle.java new file mode 100644 index 000000000000..777d9a376fdf --- /dev/null +++ b/wifi/java/android/net/wifi/aware/PeerHandle.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 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.net.wifi.aware; + +/** + * Opaque object used to represent a Wi-Fi Aware peer. Obtained from discovery sessions in + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}, used + * when sending messages e,g, {@link PublishDiscoverySession#sendMessage(PeerHandle, int, byte[])}, + * or when configuring a network link to a peer, e.g. + * {@link PublishDiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}. + * + * @hide PROPOSED_AWARE_API + */ +public class PeerHandle { + /** @hide */ + public PeerHandle(int peerId) { + this.peerId = peerId; + } + + /** @hide */ + public int peerId; +} diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java index 3925bd71ab9e..1b8ef8431f19 100644 --- a/wifi/java/android/net/wifi/aware/PublishConfig.java +++ b/wifi/java/android/net/wifi/aware/PublishConfig.java @@ -33,9 +33,9 @@ import java.util.List; /** * Defines the configuration of a Aware publish session. Built using * {@link PublishConfig.Builder}. A publish session is created using - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} or updated using - * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}. + * {@link PublishDiscoverySession#updatePublish(PublishConfig)}. * * @hide PROPOSED_AWARE_API */ @@ -184,7 +184,7 @@ public final class PublishConfig implements Parcelable { * * @hide */ - public void assertValid(WifiAwareCharacteristics characteristics) + public void assertValid(Characteristics characteristics) throws IllegalArgumentException { WifiAwareUtils.validateServiceName(mServiceName); @@ -322,12 +322,11 @@ public final class PublishConfig implements Parcelable { * Sets the number of times an unsolicited (configured using * {@link PublishConfig.Builder#setPublishType(int)}) publish session * will be broadcast. When the count is reached an event will be - * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} - * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless - * {@link #setTerminateNotificationEnabled(boolean)} disables the callback]. + * generated for {@link DiscoverySessionCallback#onSessionTerminated()} + * [unless {@link #setTerminateNotificationEnabled(boolean)} disables the callback]. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is + * Session will be terminated when {@link DiscoverySession#destroy()} is * called. * * @param publishCount Number of publish packets to broadcast. @@ -348,12 +347,11 @@ public final class PublishConfig implements Parcelable { * {@link PublishConfig.Builder#setPublishType(int)}) publish session * will be alive - broadcasting a packet. When the TTL is reached * an event will be generated for - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with - * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless + * {@link DiscoverySessionCallback#onSessionTerminated()} [unless * {@link #setTerminateNotificationEnabled(boolean)} disables the callback]. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is + * Session will be terminated when {@link DiscoverySession#destroy()} is * called. * * @param ttlSec Lifetime of a publish session in seconds. @@ -371,7 +369,7 @@ public final class PublishConfig implements Parcelable { /** * Configure whether a publish terminate notification - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported + * {@link DiscoverySessionCallback#onSessionTerminated()} is reported * back to the callback. * * @param enable If true the terminate callback will be called when the diff --git a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java b/wifi/java/android/net/wifi/aware/PublishDiscoverySession.java index 68786d17d38d..f2355b382e8d 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java +++ b/wifi/java/android/net/wifi/aware/PublishDiscoverySession.java @@ -21,32 +21,32 @@ import android.util.Log; /** * A class representing a Aware publish session. Created when - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} is called and a discovery session is created and returned in - * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}. See - * baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. This + * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)}. See + * baseline functionality of all discovery sessions in {@link DiscoverySession}. This * object allows updating an existing/running publish discovery session using * {@link #updatePublish(PublishConfig)}. * * @hide PROPOSED_AWARE_API */ -public class WifiAwarePublishDiscoverySession extends WifiAwareDiscoveryBaseSession { - private static final String TAG = "WifiAwarePublishDiscSsn"; +public class PublishDiscoverySession extends DiscoverySession { + private static final String TAG = "PublishDiscoverySession"; /** @hide */ - public WifiAwarePublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) { + public PublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) { super(manager, clientId, sessionId); } /** * Re-configure the currently active publish session. The - * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used + * {@link DiscoverySessionCallback} is not replaced - the same listener used * at creation is still used. The results of the configuration are returned using - * {@link WifiAwareDiscoverySessionCallback}: + * {@link DiscoverySessionCallback}: * <ul> - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration + * <li>{@link DiscoverySessionCallback#onSessionConfigUpdated()}: configuration * update succeeded. - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration + * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()}: configuration * update failed. The publish discovery session is still running using its previous * configuration (i.e. update failure does not terminate the session). * </ul> diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java index 0fe69a81d218..a54a4f5f5131 100644 --- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java +++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java @@ -33,9 +33,9 @@ import java.util.List; /** * Defines the configuration of a Aware subscribe session. Built using * {@link SubscribeConfig.Builder}. Subscribe is done using - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * android.os.Handler)} or - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. * * @hide PROPOSED_AWARE_API */ @@ -212,7 +212,7 @@ public final class SubscribeConfig implements Parcelable { * * @hide */ - public void assertValid(WifiAwareCharacteristics characteristics) + public void assertValid(Characteristics characteristics) throws IllegalArgumentException { WifiAwareUtils.validateServiceName(mServiceName); @@ -355,11 +355,10 @@ public final class SubscribeConfig implements Parcelable { * Sets the number of times an active ( * {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session * will broadcast. When the count is reached an event will be - * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} - * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}. + * generated for {@link DiscoverySessionCallback#onSessionTerminated()}. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is + * Session will be terminated when {@link DiscoverySession#destroy()} is * called. * * @param subscribeCount Number of subscribe packets to broadcast. @@ -380,11 +379,10 @@ public final class SubscribeConfig implements Parcelable { * {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session * will be alive - i.e. broadcasting a packet. When the TTL is reached * an event will be generated for - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with - * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}. + * {@link DiscoverySessionCallback#onSessionTerminated()}. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is + * Session will be terminated when {@link DiscoverySession#destroy()} is * called. * * @param ttlSec Lifetime of a subscribe session in seconds. @@ -404,8 +402,8 @@ public final class SubscribeConfig implements Parcelable { * Sets the match style of the subscription - how are matches from a * single match session (corresponding to the same publish action on the * peer) reported to the host (using the - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, - * byte[], List)}). The options are: only report the first match and ignore the rest + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], + * java.util.List)}). The options are: only report the first match and ignore the rest * {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single * match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default). * @@ -424,7 +422,7 @@ public final class SubscribeConfig implements Parcelable { /** * Configure whether a subscribe terminate notification - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported + * {@link DiscoverySessionCallback#onSessionTerminated()} is reported * back to the callback. * * @param enable If true the terminate callback will be called when the diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java index a0ec8093a3ab..39db1c715ae2 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java +++ b/wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java @@ -22,35 +22,35 @@ import android.util.Log; /** * A class representing a Aware subscribe session. Created when * {@link WifiAwareSession#subscribe(SubscribeConfig, - * WifiAwareDiscoverySessionCallback, android.os.Handler)} + * DiscoverySessionCallback, android.os.Handler)} * is called and a discovery session is created and returned in - * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(WifiAwareSubscribeDiscoverySession)}. - * See baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. + * {@link DiscoverySessionCallback#onSubscribeStarted(SubscribeDiscoverySession)}. + * See baseline functionality of all discovery sessions in {@link DiscoverySession}. * This object allows updating an existing/running subscribe discovery session using * {@link #updateSubscribe(SubscribeConfig)}. * * @hide PROPOSED_AWARE_API */ -public class WifiAwareSubscribeDiscoverySession extends WifiAwareDiscoveryBaseSession { - private static final String TAG = "WifiAwareSubsDiscSsn"; +public class SubscribeDiscoverySession extends DiscoverySession { + private static final String TAG = "SubscribeDiscSession"; /** * {@hide} */ - public WifiAwareSubscribeDiscoverySession(WifiAwareManager manager, int clientId, + public SubscribeDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) { super(manager, clientId, sessionId); } /** * Re-configure the currently active subscribe session. The - * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used + * {@link DiscoverySessionCallback} is not replaced - the same listener used * at creation is still used. The results of the configuration are returned using - * {@link WifiAwareDiscoverySessionCallback}: + * {@link DiscoverySessionCallback}: * <ul> - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration + * <li>{@link DiscoverySessionCallback#onSessionConfigUpdated()}: configuration * update succeeded. - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration + * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()}: configuration * update failed. The subscribe discovery session is still running using its previous * configuration (i.e. update failure does not terminate the session). * </ul> diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java index 029794dfa380..8c0a3a091579 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java @@ -58,14 +58,14 @@ import java.util.List; * The class provides access to: * <ul> * <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to - * {@link #attach(WifiAwareAttachCallback, Handler)}. + * {@link #attach(AttachCallback, Handler)}. * <li>Create discovery sessions (publish or subscribe sessions). Refer to - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)} and - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, Handler)}. + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)} and + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}. * <li>Create a Aware network specifier to be used with * {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)} * to set-up a Aware connection with a peer. Refer to - * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])} and + * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])} and * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}. * </ul> * <p> @@ -75,37 +75,37 @@ import java.util.List; * broadcast. Note that this broadcast is not sticky - you should register for it and then * check the above API to avoid a race condition. * <p> - * An application must use {@link #attach(WifiAwareAttachCallback, Handler)} to initialize a + * An application must use {@link #attach(AttachCallback, Handler)} to initialize a * Aware cluster - before making any other Aware operation. Aware cluster membership is a * device-wide operation - the API guarantees that the device is in a cluster or joins a * Aware cluster (or starts one if none can be found). Information about attach success (or - * failure) are returned in callbacks of {@link WifiAwareAttachCallback}. Proceed with Aware + * failure) are returned in callbacks of {@link AttachCallback}. Proceed with Aware * discovery or connection setup only after receiving confirmation that Aware attach - * succeeded - {@link WifiAwareAttachCallback#onAttached(WifiAwareSession)}. When an + * succeeded - {@link AttachCallback#onAttached(WifiAwareSession)}. When an * application is finished using Aware it <b>must</b> use the * {@link WifiAwareSession#destroy()} API to indicate to the Aware service that the device * may detach from the Aware cluster. The device will actually disable Aware once the last * application detaches. * <p> * Once a Aware attach is confirmed use the - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)} + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)} * or - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * Handler)} to create publish or subscribe Aware discovery sessions. Events are called on the - * provided callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the - * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)} + * provided callback object {@link DiscoverySessionCallback}. Specifically, the + * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)} * and - * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted( - * WifiAwareSubscribeDiscoverySession)} - * return {@link WifiAwarePublishDiscoverySession} and - * {@link WifiAwareSubscribeDiscoverySession} + * {@link DiscoverySessionCallback#onSubscribeStarted( + *SubscribeDiscoverySession)} + * return {@link PublishDiscoverySession} and + * {@link SubscribeDiscoverySession} * objects respectively on which additional session operations can be performed, e.g. updating - * the session {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} and - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can + * the session {@link PublishDiscoverySession#updatePublish(PublishConfig)} and + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can * also be used to send messages using the - * {@link WifiAwareDiscoveryBaseSession#sendMessage(PeerHandle, int, byte[])} APIs. When an + * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} APIs. When an * application is finished with a discovery session it <b>must</b> terminate it using the - * {@link WifiAwareDiscoveryBaseSession#destroy()} API. + * {@link DiscoverySession#destroy()} API. * <p> * Creating connections between Aware devices is managed by the standard * {@link ConnectivityManager#requestNetwork(NetworkRequest, @@ -116,7 +116,7 @@ import java.util.List; * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}. * <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} or - * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])}. + * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}. * </ul> * * @hide PROPOSED_AWARE_API @@ -226,7 +226,7 @@ public class WifiAwareManager { * Connection creation role is that of INITIATOR. Used to create a network specifier string * when requesting a Aware network. * - * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[]) + * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[]) * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[]) */ public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; @@ -235,7 +235,7 @@ public class WifiAwareManager { * Connection creation role is that of RESPONDER. Used to create a network specifier string * when requesting a Aware network. * - * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[]) + * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[]) * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[]) */ public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; @@ -307,7 +307,7 @@ public class WifiAwareManager { * @return An object specifying configuration limitations of Aware. * @hide PROPOSED_AWARE_API */ - public WifiAwareCharacteristics getCharacteristics() { + public Characteristics getCharacteristics() { try { return mService.getCharacteristics(); } catch (RemoteException e) { @@ -328,12 +328,12 @@ public class WifiAwareManager { * attachCallback}. * * @param attachCallback A callback for attach events, extended from - * {@link WifiAwareAttachCallback}. + * {@link AttachCallback}. * @param handler The Handler on whose thread to execute the callbacks of the {@code * attachCallback} object. If a null is provided then the application's main thread will be * used. */ - public void attach(@NonNull WifiAwareAttachCallback attachCallback, @Nullable Handler handler) { + public void attach(@NonNull AttachCallback attachCallback, @Nullable Handler handler) { attach(handler, null, attachCallback, null); } @@ -353,28 +353,28 @@ public class WifiAwareManager { * on startup and whenever it is updated (it is randomized at regular intervals for privacy). * The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} * permission to execute this attach request. Otherwise, use the - * {@link #attach(WifiAwareAttachCallback, Handler)} version. Note that aside from permission + * {@link #attach(AttachCallback, Handler)} version. Note that aside from permission * requirements this listener will wake up the host at regular intervals causing higher power * consumption, do not use it unless the information is necessary (e.g. for OOB discovery). * * @param attachCallback A callback for attach events, extended from - * {@link WifiAwareAttachCallback}. + * {@link AttachCallback}. * @param identityChangedListener A listener for changed identity, extended from - * {@link WifiAwareIdentityChangedListener}. + * {@link IdentityChangedListener}. * @param handler The Handler on whose thread to execute the callbacks of the {@code * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the * application's main thread will be used. */ - public void attach(@NonNull WifiAwareAttachCallback attachCallback, - @NonNull WifiAwareIdentityChangedListener identityChangedListener, + public void attach(@NonNull AttachCallback attachCallback, + @NonNull IdentityChangedListener identityChangedListener, @Nullable Handler handler) { attach(handler, null, attachCallback, identityChangedListener); } /** @hide */ public void attach(Handler handler, ConfigRequest configRequest, - WifiAwareAttachCallback attachCallback, - WifiAwareIdentityChangedListener identityChangedListener) { + AttachCallback attachCallback, + IdentityChangedListener identityChangedListener) { if (VDBG) { Log.v(TAG, "attach(): handler=" + handler + ", callback=" + attachCallback + ", configRequest=" + configRequest + ", identityChangedListener=" @@ -409,7 +409,7 @@ public class WifiAwareManager { /** @hide */ public void publish(int clientId, Looper looper, PublishConfig publishConfig, - WifiAwareDiscoverySessionCallback callback) { + DiscoverySessionCallback callback) { if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig); try { @@ -437,7 +437,7 @@ public class WifiAwareManager { /** @hide */ public void subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig, - WifiAwareDiscoverySessionCallback callback) { + DiscoverySessionCallback callback) { if (VDBG) { if (VDBG) { Log.v(TAG, @@ -672,14 +672,14 @@ public class WifiAwareManager { } /** - * Constructs a {@link WifiAwareAttachCallback} using the specified looper. + * Constructs a {@link AttachCallback} using the specified looper. * All callbacks will delivered on the thread of the specified looper. * * @param looper The looper on which to execute the callbacks. */ WifiAwareEventCallbackProxy(WifiAwareManager mgr, Looper looper, Binder binder, - final WifiAwareAttachCallback attachCallback, - final WifiAwareIdentityChangedListener identityChangedListener) { + final AttachCallback attachCallback, + final IdentityChangedListener identityChangedListener) { mAwareManager = new WeakReference<>(mgr); mLooper = looper; mBinder = binder; @@ -828,14 +828,14 @@ public class WifiAwareManager { private final WeakReference<WifiAwareManager> mAwareManager; private final boolean mIsPublish; - private final WifiAwareDiscoverySessionCallback mOriginalCallback; + private final DiscoverySessionCallback mOriginalCallback; private final int mClientId; private final Handler mHandler; - private WifiAwareDiscoveryBaseSession mSession; + private DiscoverySession mSession; WifiAwareDiscoverySessionCallbackProxy(WifiAwareManager mgr, Looper looper, - boolean isPublish, WifiAwareDiscoverySessionCallback originalCallback, + boolean isPublish, DiscoverySessionCallback originalCallback, int clientId) { mAwareManager = new WeakReference<>(mgr); mIsPublish = isPublish; @@ -1006,13 +1006,13 @@ public class WifiAwareManager { } if (mIsPublish) { - WifiAwarePublishDiscoverySession session = new WifiAwarePublishDiscoverySession(mgr, + PublishDiscoverySession session = new PublishDiscoverySession(mgr, mClientId, sessionId); mSession = session; mOriginalCallback.onPublishStarted(session); } else { - WifiAwareSubscribeDiscoverySession - session = new WifiAwareSubscribeDiscoverySession(mgr, mClientId, sessionId); + SubscribeDiscoverySession + session = new SubscribeDiscoverySession(mgr, mClientId, sessionId); mSession = session; mOriginalCallback.onSubscribeStarted(session); } @@ -1027,18 +1027,7 @@ public class WifiAwareManager { Log.w(TAG, "Proxy: onSessionTerminated called but mSession is null!?"); } mAwareManager.clear(); - mOriginalCallback.onSessionTerminated(reason); + mOriginalCallback.onSessionTerminated(); } } - - /** @hide PROPOSED_AWARE_API */ - public static class PeerHandle { - /** @hide */ - public PeerHandle(int peerId) { - this.peerId = peerId; - } - - /** @hide */ - public int peerId; - } } diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java index 005895a28043..e3ebe860f55f 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java @@ -65,7 +65,7 @@ public class WifiAwareSession { * session-wide destroy. * <p> * An application may re-attach after a destroy using - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, Handler)} . + * {@link WifiAwareManager#attach(AttachCallback, Handler)} . */ public void destroy() { WifiAwareManager mgr = mMgr.get(); @@ -95,22 +95,22 @@ public class WifiAwareSession { /** * Issue a request to the Aware service to create a new Aware publish discovery session, using * the specified {@code publishConfig} configuration. The results of the publish operation - * are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}: + * are routed to the callbacks of {@link DiscoverySessionCallback}: * <ul> * <li> - * {@link WifiAwareDiscoverySessionCallback#onPublishStarted( - * WifiAwarePublishDiscoverySession)} + * {@link DiscoverySessionCallback#onPublishStarted( + *PublishDiscoverySession)} * is called when the publish session is created and provides a handle to the session. * Further operations on the publish session can be executed on that object. - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the + * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()} is called if the * publish operation failed. * </ul> * <p> * Other results of the publish session operations will also be routed to callbacks * on the {@code callback} object. The resulting publish session can be modified using - * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}. + * {@link PublishDiscoverySession#updatePublish(PublishConfig)}. * <p> - * An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to + * An application must use the {@link DiscoverySession#destroy()} to * terminate the publish discovery session once it isn't needed. This will free * resources as well terminate any on-air transmissions. * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} @@ -118,13 +118,13 @@ public class WifiAwareSession { * * @param publishConfig The {@link PublishConfig} specifying the * configuration of the requested publish session. - * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for + * @param callback A {@link DiscoverySessionCallback} derived object to be used for * session event callbacks. * @param handler The Handler on whose thread to execute the callbacks of the {@code * callback} object. If a null is provided then the application's main thread will be used. */ public void publish(@NonNull PublishConfig publishConfig, - @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) { + @NonNull DiscoverySessionCallback callback, @Nullable Handler handler) { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { Log.e(TAG, "publish: called post GC on WifiAwareManager"); @@ -141,22 +141,22 @@ public class WifiAwareSession { /** * Issue a request to the Aware service to create a new Aware subscribe discovery session, using * the specified {@code subscribeConfig} configuration. The results of the subscribe - * operation are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}: + * operation are routed to the callbacks of {@link DiscoverySessionCallback}: * <ul> * <li> - * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted( - * WifiAwareSubscribeDiscoverySession)} + * {@link DiscoverySessionCallback#onSubscribeStarted( + *SubscribeDiscoverySession)} * is called when the subscribe session is created and provides a handle to the session. * Further operations on the subscribe session can be executed on that object. - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the + * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()} is called if the * subscribe operation failed. * </ul> * <p> * Other results of the subscribe session operations will also be routed to callbacks * on the {@code callback} object. The resulting subscribe session can be modified using - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. * <p> - * An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to + * An application must use the {@link DiscoverySession#destroy()} to * terminate the subscribe discovery session once it isn't needed. This will free * resources as well terminate any on-air transmissions. * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} @@ -164,13 +164,13 @@ public class WifiAwareSession { * * @param subscribeConfig The {@link SubscribeConfig} specifying the * configuration of the requested subscribe session. - * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for + * @param callback A {@link DiscoverySessionCallback} derived object to be used for * session event callbacks. * @param handler The Handler on whose thread to execute the callbacks of the {@code * callback} object. If a null is provided then the application's main thread will be used. */ public void subscribe(@NonNull SubscribeConfig subscribeConfig, - @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) { + @NonNull DiscoverySessionCallback callback, @Nullable Handler handler) { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { Log.e(TAG, "publish: called post GC on WifiAwareManager"); @@ -193,7 +193,7 @@ public class WifiAwareSession { * This API is targeted for applications which can obtain the peer MAC address using OOB * (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer - * when using Aware discovery use the alternative network specifier method - - * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(WifiAwareManager.PeerHandle, + * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, * byte[])}. * * @param role The role of this device: diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java index 24c0127cb11b..a396d8775ab6 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -67,19 +67,19 @@ public class WifiAwareManagerTest { public Context mockContext; @Mock - public WifiAwareAttachCallback mockCallback; + public AttachCallback mockCallback; @Mock - public WifiAwareDiscoverySessionCallback mockSessionCallback; + public DiscoverySessionCallback mockSessionCallback; @Mock public IWifiAwareManager mockAwareService; @Mock - public WifiAwarePublishDiscoverySession mockPublishSession; + public PublishDiscoverySession mockPublishSession; @Mock - public WifiAwareSubscribeDiscoverySession mockSubscribeSession; + public SubscribeDiscoverySession mockSubscribeSession; @Mock public RttManager.RttListener mockRttListener; @@ -276,7 +276,7 @@ public class WifiAwareManagerTest { final int sessionId = 123; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final PublishConfig publishConfig = new PublishConfig.Builder().build(); - final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873); + final PeerHandle peerHandle = new PeerHandle(873); final String string1 = "hey from here..."; final byte[] matchFilter = { 1, 12, 2, 31, 32 }; final int messageId = 2123; @@ -290,10 +290,9 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor - .forClass(WifiAwarePublishDiscoverySession.class); - ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass( - WifiAwareManager.PeerHandle.class); + ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(PublishDiscoverySession.class); + ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class); ArgumentCaptor<List<byte[]>> matchFilterCaptor = ArgumentCaptor.forClass( (Class) List.class); @@ -377,7 +376,6 @@ public class WifiAwareManagerTest { final int sessionId = 123; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final PublishConfig publishConfig = new PublishConfig.Builder().build(); - final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE; InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, mockPublishSession); @@ -387,8 +385,8 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor - .forClass(WifiAwarePublishDiscoverySession.class); + ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(PublishDiscoverySession.class); // (1) connect successfully mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); @@ -404,10 +402,10 @@ public class WifiAwareManagerTest { inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), sessionProxyCallback.capture()); sessionProxyCallback.getValue().onSessionStarted(sessionId); - sessionProxyCallback.getValue().onSessionTerminated(reason); + sessionProxyCallback.getValue().onSessionTerminated(0); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture()); - inOrder.verify(mockSessionCallback).onSessionTerminated(reason); + inOrder.verify(mockSessionCallback).onSessionTerminated(); // (3) failure when trying to update: NOP publishSession.getValue().updatePublish(publishConfig); @@ -428,7 +426,7 @@ public class WifiAwareManagerTest { final int sessionId = 123; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873); + final PeerHandle peerHandle = new PeerHandle(873); final String string1 = "hey from here..."; final byte[] matchFilter = { 1, 12, 3, 31, 32 }; // bad data! final int messageId = 2123; @@ -442,10 +440,9 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor - .forClass(WifiAwareSubscribeDiscoverySession.class); - ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass( - WifiAwareManager.PeerHandle.class); + ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor + .forClass(SubscribeDiscoverySession.class); + ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class); // (0) connect + success mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); @@ -516,7 +513,6 @@ public class WifiAwareManagerTest { final int sessionId = 123; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE; InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, mockSubscribeSession); @@ -526,8 +522,8 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor - .forClass(WifiAwareSubscribeDiscoverySession.class); + ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor + .forClass(SubscribeDiscoverySession.class); // (1) connect successfully mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); @@ -543,10 +539,10 @@ public class WifiAwareManagerTest { inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig), sessionProxyCallback.capture()); sessionProxyCallback.getValue().onSessionStarted(sessionId); - sessionProxyCallback.getValue().onSessionTerminated(reason); + sessionProxyCallback.getValue().onSessionTerminated(0); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture()); - inOrder.verify(mockSessionCallback).onSessionTerminated(reason); + inOrder.verify(mockSessionCallback).onSessionTerminated(); // (3) failure when trying to update: NOP subscribeSession.getValue().updateSubscribe(subscribeConfig); @@ -892,8 +888,8 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor - .forClass(WifiAwarePublishDiscoverySession.class); + ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(PublishDiscoverySession.class); ArgumentCaptor<RttManager.ParcelableRttParams> rttParamCaptor = ArgumentCaptor .forClass(RttManager.ParcelableRttParams.class); ArgumentCaptor<RttManager.RttResult[]> rttResultsCaptor = ArgumentCaptor @@ -953,7 +949,7 @@ public class WifiAwareManagerTest { public void testNetworkSpecifierWithClient() throws Exception { final int clientId = 4565; final int sessionId = 123; - final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(123412); + final PeerHandle peerHandle = new PeerHandle(123412); final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; final String token = "Some arbitrary token string - can really be anything"; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); @@ -967,8 +963,8 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor - .forClass(WifiAwarePublishDiscoverySession.class); + ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(PublishDiscoverySession.class); InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, mockPublishSession, mockRttListener); |